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

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