1#ifndef STAN_MATH_PRIM_PROB_MULTI_NORMAL_LPDF_HPP
2#define STAN_MATH_PRIM_PROB_MULTI_NORMAL_LPDF_HPP
24template <
bool propto,
typename T_y,
typename T_loc,
typename T_covar,
25 require_any_not_vector_vt<is_stan_scalar, T_y, T_loc>* =
nullptr,
27 T_y, T_loc, T_covar>* =
nullptr>
30 const T_covar& Sigma) {
34 using matrix_partials_t
35 = Eigen::Matrix<T_partials_return, Eigen::Dynamic, Eigen::Dynamic>;
36 using vector_partials_t = Eigen::Matrix<T_partials_return, Eigen::Dynamic, 1>;
41 static const char* function =
"multi_normal_lpdf";
47 if (number_of_y == 0 || number_of_mu == 0) {
53 T_Sigma_ref Sigma_ref = Sigma;
57 const int K = Sigma.rows();
59 int size_y = y_vec[0].size();
60 int size_mu = mu_vec[0].size();
63 for (
size_t i = 1, size_mvt_y =
size_mvt(y); i < size_mvt_y; i++) {
65 "Size of one of the vectors of "
66 "the random variable",
68 "Size of the first vector of the "
73 for (
size_t i = 1, size_mvt_mu =
size_mvt(mu); i < size_mvt_mu; i++) {
75 "Size of one of the vectors of "
76 "the location variable",
78 "Size of the first vector of the "
84 "size of location parameter", size_mu);
86 "rows of covariance parameter", Sigma.rows());
88 "columns of covariance parameter", Sigma.cols());
90 for (
size_t i = 0; i < size_vec; i++) {
107 T_partials_return logp(0);
114 vector_partials_t half(size_vec);
115 vector_partials_t y_val_minus_mu_val(size_vec);
117 T_partials_return sum_lp_vec(0.0);
118 for (
size_t i = 0; i < size_vec; i++) {
121 y_val_minus_mu_val =
eval(y_val - mu_val);
124 sum_lp_vec +=
dot_product(y_val_minus_mu_val, half);
127 partials_vec<0>(ops_partials)[i] += -half;
130 partials_vec<1>(ops_partials)[i] += half;
133 partials_vec<2>(ops_partials)[i] += 0.5 * half * half.transpose();
137 logp += -0.5 * sum_lp_vec;
146 matrix_partials_t inv_Sigma
151 partials<2>(ops_partials) += -0.5 * size_vec * inv_Sigma;
155 return ops_partials.build(logp);
158template <
bool propto,
typename T_y,
typename T_loc,
typename T_covar,
161 T_y, T_loc, T_covar>* =
nullptr>
164 const T_covar& Sigma) {
168 using matrix_partials_t
169 = Eigen::Matrix<T_partials_return, Eigen::Dynamic, Eigen::Dynamic>;
170 using vector_partials_t = Eigen::Matrix<T_partials_return, Eigen::Dynamic, 1>;
175 static const char* function =
"multi_normal_lpdf";
179 T_mu_ref mu_ref = mu;
180 T_Sigma_ref Sigma_ref = Sigma;
185 const int size_y = y_ref.size();
186 const int size_mu = mu_ref.size();
187 const unsigned int K = Sigma.rows();
193 "size of location parameter", size_mu);
195 "rows of covariance parameter", Sigma.rows());
197 "columns of covariance parameter", Sigma.cols());
211 T_partials_return logp(0);
213 if (include_summand<propto>::value) {
217 if (include_summand<propto, T_y, T_loc, T_covar_elem>::value) {
218 vector_partials_t half(size_y);
219 vector_partials_t y_val_minus_mu_val =
eval(y_val - mu_val);
223 if (is_constant<T_covar_elem>::value) {
226 if (include_summand<propto>::value) {
230 matrix_partials_t inv_Sigma
233 half.noalias() = inv_Sigma * y_val_minus_mu_val;
237 edge<2>(ops_partials).partials_
238 += 0.5 * (half * half.transpose() - inv_Sigma);
241 logp += -0.5 *
dot_product(y_val_minus_mu_val, half);
243 if (!is_constant_all<T_y>::value) {
244 partials<0>(ops_partials) += -half;
246 if (!is_constant_all<T_loc>::value) {
247 partials<1>(ops_partials) += half;
251 return ops_partials.build(logp);
254template <
typename T_y,
typename T_loc,
typename T_covar>
256 const T_y& y,
const T_loc& mu,
const T_covar& Sigma) {
257 return multi_normal_lpdf<false>(y, mu, Sigma);
This class provides a low-cost wrapper for situations where you either need an Eigen Vector or RowVec...
void check_symmetric(const char *function, const char *name, const matrix_cl< T > &y)
Check if the matrix_cl is symmetric.
require_all_not_t< is_nonscalar_prim_or_rev_kernel_expression< std::decay_t< Types > >... > require_all_not_nonscalar_prim_or_rev_kernel_expression_t
Require none of the types satisfy is_nonscalar_prim_or_rev_kernel_expression.
int64_t size_mvt(const ScalarT &)
Provides the size of a multivariate argument.
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
int64_t size(const T &m)
Returns the size (number of the elements) of a matrix_cl or var_value<matrix_cl<T>>.
require_all_t< container_type_check_base< is_vector, value_type_t, TypeCheck, Check >... > require_all_vector_vt
Require all of the types satisfy is_vector.
value_type_t< T > log_determinant_ldlt(LDLT_factor< T > &A)
Returns log(abs(det(A))) given a LDLT_factor of A.
auto make_ldlt_factor(const T &A)
Make an LDLT_factor with matrix type plain_type_t<T>
return_type_t< T_y, T_loc, T_covar > multi_normal_lpdf(const T_y &y, const T_loc &mu, const T_covar &Sigma)
void check_consistent_sizes_mvt(const char *)
Trivial no input case, this function is a no-op.
T eval(T &&arg)
Inputs which have a plain_type equal to the own time are forwarded unmodified (for Eigen expressions ...
T value_of(const fvar< T > &v)
Return the value of the specified variable.
const double NEG_LOG_SQRT_TWO_PI
The value of minus the natural logarithm of the square root of , .
int64_t max_size_mvt(const T1 &x1, const Ts &... xs)
Calculate the size of the largest multivariate input.
Eigen::Matrix< value_type_t< EigMat >, Eigen::Dynamic, EigMat::ColsAtCompileTime > mdivide_left_ldlt(LDLT_factor< T > &A, const EigMat &b)
Returns the solution of the system Ax=b given an LDLT_factor of A.
void check_finite(const char *function, const char *name, const T_y &y)
Return true if all values in y are finite.
void check_ldlt_factor(const char *function, const char *name, LDLT_factor< T > &A)
Raise domain error if the specified LDLT factor is invalid.
void check_not_nan(const char *function, const char *name, const T_y &y)
Check if y is not NaN.
void check_positive(const char *function, const char *name, const T_y &y)
Check if y is positive.
void check_size_match(const char *function, const char *name_i, T_size1 i, const char *name_j, T_size2 j)
Check if the provided sizes match.
auto dot_product(const T_a &a, const T_b &b)
Returns the dot product of the specified vectors.
auto as_value_column_vector_or_scalar(T &&a)
Extract values from input argument and transform to a column vector.
auto make_partials_propagator(Ops &&... ops)
Construct an partials_propagator.
typename ref_type_if< true, T >::type ref_type_t
typename partials_return_type< Args... >::type partials_return_t
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Metaprogramming struct to detect whether a given type is constant in the mathematical sense (not the ...
Extends std::true_type when instantiated with zero or more template parameters, all of which extend t...
Template metaprogram to calculate whether a summand needs to be included in a proportional (log) prob...