1#ifndef STAN_MATH_REV_FUN_READ_CORR_L_HPP
2#define STAN_MATH_REV_FUN_READ_CORR_L_HPP
35template <
typename T, require_var_vector_t<T>* =
nullptr>
40 return ret_type(Eigen::MatrixXd());
43 return ret_type(Eigen::MatrixXd::Identity(1, 1));
55 L.col(0).tail(pull) = CPCs.val().head(pull);
56 arena_acc.tail(pull) = 1.0 - CPCs.val().head(pull).array().square();
57 for (
size_t i = 1; i < (K - 1); i++) {
61 const auto& cpc_seg = CPCs.val().array().segment(pos, pull);
62 L.coeffRef(i, i) =
sqrt(arena_acc.coeff(i - 1));
63 L.col(i).tail(pull) = cpc_seg * arena_acc.tail(pull).sqrt();
64 arena_acc.tail(pull) = arena_acc.tail(pull) * (1.0 - cpc_seg.square());
67 L.coeffRef(K - 1, K - 1) =
sqrt(arena_acc.coeff(K - 2));
72 Eigen::ArrayXd acc_val = arena_acc;
73 Eigen::ArrayXd acc_adj = Eigen::ArrayXd::Zero(K - 1);
75 acc_adj.coeffRef(K - 2) += 0.5 * L_res.adj().coeff(K - 1, K - 1)
76 / L_res.val().coeff(K - 1, K - 1);
78 int pos = CPCs.size() - 1;
79 for (
size_t i = K - 2; i > 0; --i) {
82 const auto& cpc_seg_val = CPCs.val().array().segment(pos, pull);
83 auto cpc_seg_adj = CPCs.adj().array().segment(pos, pull);
84 acc_val.tail(pull) /= 1.0 - cpc_seg_val.square();
86 -= 2.0 * acc_adj.tail(pull) * acc_val.tail(pull) * cpc_seg_val;
88 = (acc_adj.tail(pull).array() * (1.0 - cpc_seg_val.square())).eval();
90 += L_res.adj().array().col(i).tail(pull) * acc_val.tail(pull).sqrt();
91 acc_adj.tail(pull) += 0.5 * L_res.adj().array().col(i).tail(pull)
92 * cpc_seg_val / acc_val.tail(pull).sqrt();
93 acc_adj.coeffRef(i - 1)
94 += 0.5 * L_res.adj().coeff(i, i) / L_res.val().coeff(i, i);
100 CPCs.adj().array().head(pull)
101 -= 2.0 * acc_adj.tail(pull) * CPCs.val().array().head(pull);
102 CPCs.adj().head(pull) += L_res.adj().col(0).tail(pull);
105 return ret_type(L_res);
133template <
typename T1,
typename T2, require_var_vector_t<T1>* =
nullptr,
134 require_stan_scalar_t<T2>* =
nullptr>
136 using ret_val_type = Eigen::MatrixXd;
140 return ret_type(ret_val_type());
143 return ret_type(Eigen::MatrixXd::Identity(1, 1));
151 for (
size_t k = 1; k <= (K - 2); k++) {
152 for (
size_t i = k + 1; i <= K; i++) {
153 acc_val += (K - k - 1) *
log1m(
square(CPCs.val().coeff(pos)));
158 log_prob += 0.5 * acc_val;
161 double acc_adj = log_prob.adj() * 0.5;
163 size_t pos = CPCs.size() - 2;
164 for (
size_t k = K - 2; k >= 1; --k) {
165 for (
size_t i = K; i >= k + 1; --i) {
166 CPCs.adj().coeffRef(pos) -= 2.0 * acc_adj * (K - k - 1)
167 * CPCs.val().coeff(pos)
168 / (1.0 -
square(CPCs.val().coeff(pos)));
void reverse_pass_callback(F &&functor)
Puts a callback on the autodiff stack to be called in reverse pass.
fvar< T > sqrt(const fvar< T > &x)
fvar< T > log1m(const fvar< T > &x)
Eigen::Matrix< value_type_t< T >, Eigen::Dynamic, Eigen::Dynamic > read_corr_L(const T &CPCs, size_t K)
Return the Cholesky factor of the correlation matrix of the specified dimensionality corresponding to...
fvar< T > square(const fvar< T > &x)
typename internal::arena_type_impl< std::decay_t< T > >::type arena_t
Determines a type that can be used in place of T that does any dynamic allocations on the AD stack.
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...