Stan Math Library  2.11.0
reverse mode automatic differentiation
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>
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
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition: value_of.hpp:16
fvar< T > exp(const fvar< T > &x)
Definition: exp.hpp:10
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
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 Home Page ] © 2011–2016, Stan Development Team.