Stan Math Library: stan/math/fwd/scal/fun/log_mix.hpp Source File

| Stan Math Library 2.10.0 reverse mode automatic differentiation

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

log_mix.hpp
Go to the documentation of this file.
1 #ifndef STAN_MATH_FWD_SCAL_FUN_LOG_MIX_HPP
2 #define STAN_MATH_FWD_SCAL_FUN_LOG_MIX_HPP
3
4 #include <stan/math/fwd/core.hpp>
5 #include <stan/math/prim/scal/fun/value_of.hpp>
6 #include <stan/math/prim/scal/fun/log_mix.hpp>
7 #include <boost/math/tools/promotion.hpp>
8 #include <cmath>
9
10 namespace stan {
11
12 namespace math {
13
14 /* Returns an array of size N with partials of log_mix wrt to its
15 * parameters instantiated as fvar<T>
16 *
17 * @tparam T_theta theta scalar type
18 * @tparam T_lambda1 lambda_1 scalar type
19 * @tparam T_lambda2 lambda_2 scalar type
20 *
21 * @param[in] N output array size
22 * @param[in] theta_d mixing proportion theta
23 * @param[in] lambda1_d log_density with mixing proportion theta
24 * @param[in] lambda2_d log_density with mixing proportion 1.0 - theta
25 * @param[out] partials_array array of partials derivatives
26 */
27 template <typename T_theta, typename T_lambda1, typename T_lambda2, int N>
28 inline void
29 log_mix_partial_helper(const T_theta& theta,
30 const T_lambda1& lambda1,
31 const T_lambda2& lambda2,
32 typename
33 boost::math::tools::promote_args<
34 T_theta, T_lambda1, T_lambda2>::type
35 (&partials_array)[N]) {
36 using std::exp;
37 using boost::is_same;
38 using boost::math::tools::promote_args;
39 typedef typename promote_args<T_theta, T_lambda1, T_lambda2>::type
40 partial_return_type;
41
42 typename promote_args<T_lambda1, T_lambda2>::type lam2_m_lam1
43 = lambda2 - lambda1;
44 typename promote_args<T_lambda1, T_lambda2>::type exp_lam2_m_lam1
45 = exp(lam2_m_lam1);
46 typename promote_args<T_lambda1, T_lambda2>::type one_m_exp_lam2_m_lam1
47 = 1.0 - exp_lam2_m_lam1;
48 typename promote_args<double, T_theta>::type one_m_t = 1.0 - theta;
49 partial_return_type one_m_t_prod_exp_lam2_m_lam1
50 = one_m_t * exp_lam2_m_lam1;
51 partial_return_type t_plus_one_m_t_prod_exp_lam2_m_lam1
52 = theta + one_m_t_prod_exp_lam2_m_lam1;
53 partial_return_type one_d_t_plus_one_m_t_prod_exp_lam2_m_lam1
54 = 1.0 / t_plus_one_m_t_prod_exp_lam2_m_lam1;
55
56 unsigned int offset = 0;
57 if (is_same<T_theta, partial_return_type>::value) {
58 partials_array[offset]
59 = one_m_exp_lam2_m_lam1
60 * one_d_t_plus_one_m_t_prod_exp_lam2_m_lam1;
61 ++offset;
62 }
63 if (is_same<T_lambda1, partial_return_type>::value) {
64 partials_array[offset]
65 = theta * one_d_t_plus_one_m_t_prod_exp_lam2_m_lam1;
66 ++offset;
67 }
68 if (is_same<T_lambda2, partial_return_type>::value) {
69 partials_array[offset]
70 = one_m_t_prod_exp_lam2_m_lam1
71 * one_d_t_plus_one_m_t_prod_exp_lam2_m_lam1;
72 }
73 }
74
114 template <typename T>
115 inline
116 fvar<T>
117 log_mix(const fvar<T>& theta, const fvar<T>& lambda1,
118 const fvar<T>& lambda2) {
119 using stan::math::log_mix;
120 using stan::math::value_of;
121
122 if (lambda1.val_ > lambda2.val_) {
123 fvar<T> partial_deriv_array[3];
124 log_mix_partial_helper(theta, lambda1, lambda2, partial_deriv_array);
125 return fvar<T>(log_mix(theta.val_, lambda1.val_, lambda2.val_),
126 theta.d_ * value_of(partial_deriv_array[0])
127 + lambda1.d_ * value_of(partial_deriv_array[1])
128 + lambda2.d_ * value_of(partial_deriv_array[2]));
129 } else {
130 fvar<T> partial_deriv_array[3];
131 log_mix_partial_helper(1.0 - theta, lambda2, lambda1,
132 partial_deriv_array);
133 return fvar<T>(log_mix(theta.val_, lambda1.val_, lambda2.val_),
134 -theta.d_ * value_of(partial_deriv_array[0])
135 + lambda1.d_ * value_of(partial_deriv_array[2])
136 + lambda2.d_ * value_of(partial_deriv_array[1]));
137 }
138 }
139
140 template <typename T>
141 inline
142 fvar<T>
143 log_mix(const fvar<T>& theta, const fvar<T>& lambda1,
144 const double lambda2) {
145 using stan::math::log_mix;
146 using stan::math::value_of;
147
148 if (lambda1.val_ > lambda2) {
149 fvar<T> partial_deriv_array[2];
150 log_mix_partial_helper(theta, lambda1, lambda2,
151 partial_deriv_array);
152 return fvar<T>(log_mix(theta.val_, lambda1.val_, lambda2),
153 theta.d_ * value_of(partial_deriv_array[0])
154 + lambda1.d_ * value_of(partial_deriv_array[1]));
155 } else {
156 fvar<T> partial_deriv_array[2];
157 log_mix_partial_helper(1.0 - theta, lambda2, lambda1,
158 partial_deriv_array);
159 return fvar<T>(log_mix(theta.val_, lambda1.val_, lambda2),
160 -theta.d_ * value_of(partial_deriv_array[0])
161 + lambda1.d_ * value_of(partial_deriv_array[1]));
162 }
163 }
164
165 template<typename T>
166 inline
167 fvar<T>
168 log_mix(const fvar<T>& theta, const double lambda1,
169 const fvar<T>& lambda2) {
170 using stan::math::log_mix;
171 using stan::math::value_of;
172
173 if (lambda1 > lambda2.val_) {
174 fvar<T> partial_deriv_array[2];
175 log_mix_partial_helper(theta, lambda1, lambda2,
176 partial_deriv_array);
177 return fvar<T>(log_mix(theta.val_, lambda1, lambda2.val_),
178 theta.d_ * value_of(partial_deriv_array[0])
179 + lambda2.d_ * value_of(partial_deriv_array[1]));
180 } else {
181 fvar<T> partial_deriv_array[2];
182 log_mix_partial_helper(1.0 - theta, lambda2, lambda1,
183 partial_deriv_array);
184 return fvar<T>(log_mix(theta.val_, lambda1, lambda2.val_),
185 -theta.d_ * value_of(partial_deriv_array[0])
186 + lambda2.d_ * value_of(partial_deriv_array[1]));
187 }
188 }
189
190 template<typename T>
191 inline
192 fvar<T>
193 log_mix(const double theta, const fvar<T>& lambda1,
194 const fvar<T>& lambda2) {
195 using stan::math::log_mix;
196 using stan::math::value_of;
197
198 if (lambda1.val_ > lambda2.val_) {
199 fvar<T> partial_deriv_array[2];
200 log_mix_partial_helper(theta, lambda1, lambda2, partial_deriv_array);
201 return fvar<T>(log_mix(theta, lambda1.val_, lambda2.val_),
202 lambda1.d_ * value_of(partial_deriv_array[0])
203 + lambda2.d_ * value_of(partial_deriv_array[1]));
204 } else {
205 fvar<T> partial_deriv_array[2];
206 log_mix_partial_helper(1.0 - theta, lambda2, lambda1,
207 partial_deriv_array);
208 return fvar<T>(log_mix(theta, lambda1.val_, lambda2.val_),
209 lambda1.d_ * value_of(partial_deriv_array[1])
210 + lambda2.d_ * value_of(partial_deriv_array[0]));
211 }
212 }
213
214 template<typename T>
215 inline
216 fvar<T>
217 log_mix(const fvar<T>& theta, const double lambda1, const double lambda2) {
218 using stan::math::log_mix;
219 using stan::math::value_of;
220
221 if (lambda1 > lambda2) {
222 fvar<T> partial_deriv_array[1];
223 log_mix_partial_helper(theta, lambda1, lambda2, partial_deriv_array);
224 return fvar<T>(log_mix(theta.val_, lambda1, lambda2),
225 theta.d_ * value_of(partial_deriv_array[0]));
226 } else {
227 fvar<T> partial_deriv_array[1];
228 log_mix_partial_helper(1.0 - theta, lambda2, lambda1,
229 partial_deriv_array);
230 return fvar<T>(log_mix(theta.val_, lambda1, lambda2),
231 -theta.d_ * value_of(partial_deriv_array[0]));
232 }
233 }
234
235 template<typename T>
236 inline
237 fvar<T>
238 log_mix(const double theta, const fvar<T>& lambda1, const double lambda2) {
239 using stan::math::log_mix;
240 using stan::math::value_of;
241
242 if (lambda1.val_ > lambda2) {
243 fvar<T> partial_deriv_array[1];
244 log_mix_partial_helper(theta, lambda1, lambda2, partial_deriv_array);
245 return fvar<T>(log_mix(theta, lambda1.val_, lambda2),
246 lambda1.d_ * value_of(partial_deriv_array[0]));
247 } else {
248 fvar<T> partial_deriv_array[1];
249 log_mix_partial_helper(1.0 - theta, lambda2, lambda1,
250 partial_deriv_array);
251 return fvar<T>(log_mix(theta, lambda1.val_, lambda2),
252 lambda1.d_ * value_of(partial_deriv_array[0]));
253 }
254 }
255
256 template<typename T>
257 inline
258 fvar<T>
259 log_mix(const double theta, const double lambda1, const fvar<T>& lambda2) {
260 using stan::math::log_mix;
261 using stan::math::value_of;
262
263 if (lambda1 > lambda2.val_) {
264 fvar<T> partial_deriv_array[1];
265 log_mix_partial_helper(theta, lambda1, lambda2, partial_deriv_array);
266 return fvar<T>(log_mix(theta, lambda1, lambda2.val_),
267 lambda2.d_ * value_of(partial_deriv_array[0]));
268 } else {
269 fvar<T> partial_deriv_array[1];
270 log_mix_partial_helper(1.0 - theta, lambda2, lambda1,
271 partial_deriv_array);
272 return fvar<T>(log_mix(theta, lambda1, lambda2.val_),
273 lambda2.d_ * value_of(partial_deriv_array[0]));
274 }
275 }
276 }
277 }
278 #endif
core.hpp
stan::math::fvar::d_
T d_
Definition: fvar.hpp:15
stan
Definition: log_sum_exp.hpp:8
stan::math::value_of
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition: value_of.hpp:16
stan::math::fvar::val_
T val_
Definition: fvar.hpp:14
stan::math::exp
fvar< T > exp(const fvar< T > &x)
Definition: exp.hpp:10
log_mix.hpp
stan::math::log_mix_partial_helper
void log_mix_partial_helper(const T_theta &theta, const T_lambda1 &lambda1, const T_lambda2 &lambda2, typename boost::math::tools::promote_args< T_theta, T_lambda1, T_lambda2 >::type(&partials_array)[N])
Definition: log_mix.hpp:29
value_of.hpp
stan::math::log_mix
fvar< T > log_mix(const fvar< T > &theta, const fvar< T > &lambda1, const fvar< T > &lambda2)
Return the log mixture density with specified mixing proportion and log densities and its derivative ...
Definition: log_mix.hpp:117
stan::math::fvar
Definition: fvar.hpp:13

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