1#ifndef STAN_MATH_REV_CONSTRAINT_CHOLESKY_CORR_CONSTRAIN_HPP
2#define STAN_MATH_REV_CONSTRAINT_CHOLESKY_CORR_CONSTRAIN_HPP
27template <
typename T, require_var_vector_t<T>* =
nullptr>
30 int k_choose_2 = (K * (K - 1)) / 2;
32 "k_choose_2", k_choose_2);
35 return Eigen::MatrixXd();
41 x_val.coeffRef(0, 0) = 1;
43 for (
int i = 1; i < K; ++i) {
44 x_val.coeffRef(i, 0) = z.val().coeff(k);
46 double sum_sqs =
square(x_val.coeff(i, 0));
47 for (
int j = 1; j < i; ++j) {
48 x_val.coeffRef(i, j) = z.val().coeff(k) *
sqrt(1.0 - sum_sqs);
50 sum_sqs +=
square(x_val.coeff(i, j));
52 x_val.coeffRef(i, i) =
sqrt(1.0 - sum_sqs);
59 for (
int i = K - 1; i > 0; --i) {
60 double sum_sqs_val = 1.0 -
square(x.val().coeffRef(i, i));
61 double sum_sqs_adj = -0.5 * x.adj().coeff(i, i) / x.val().coeff(i, i);
62 for (
int j = i - 1; j > 0; --j) {
63 x.adj().coeffRef(i, j) += 2 * sum_sqs_adj * x.val().coeff(i, j);
64 sum_sqs_val -=
square(x.val().coeff(i, j));
66 sum_sqs_adj += -0.5 * x.adj().coeffRef(i, j) * z.val().coeff(k)
67 /
sqrt(1.0 - sum_sqs_val);
68 z.adj().coeffRef(k) += x.adj().coeffRef(i, j) *
sqrt(1.0 - sum_sqs_val);
70 x.adj().coeffRef(i, 0) += 2 * sum_sqs_adj * x.val().coeff(i, 0);
72 z.adj().coeffRef(k) += x.adj().coeffRef(i, 0);
91template <
typename T, require_var_vector_t<T>* =
nullptr>
97 int k_choose_2 = (K * (K - 1)) / 2;
99 "k_choose_2", k_choose_2);
102 return Eigen::MatrixXd();
108 x_val.coeffRef(0, 0) = 1;
111 for (
int i = 1; i < K; ++i) {
112 x_val.coeffRef(i, 0) = z.val().coeff(k);
114 double sum_sqs =
square(x_val.coeff(i, 0));
115 for (
int j = 1; j < i; ++j) {
116 lp_val += 0.5 *
log1m(sum_sqs);
117 x_val.coeffRef(i, j) = z.val().coeff(k) *
sqrt(1.0 - sum_sqs);
119 sum_sqs +=
square(x_val.coeff(i, j));
121 x_val.coeffRef(i, i) =
sqrt(1.0 - sum_sqs);
129 for (
int i = K - 1; i > 0; --i) {
130 double sum_sqs_val = 1.0 -
square(x.val().coeffRef(i, i));
131 double sum_sqs_adj = -0.5 * x.adj().coeff(i, i) / x.val().coeff(i, i);
132 for (
int j = i - 1; j > 0; --j) {
133 x.adj().coeffRef(i, j) += 2 * sum_sqs_adj * x.val().coeff(i, j);
134 sum_sqs_val -=
square(x.val().coeff(i, j));
137 sum_sqs_adj += -0.5 * x.adj().coeffRef(i, j) * z.val().coeff(k)
138 /
sqrt(1.0 - sum_sqs_val);
139 z.adj().coeffRef(k) += x.adj().coeffRef(i, j) *
sqrt(1.0 - sum_sqs_val);
140 sum_sqs_adj -= 0.5 * lp.adj() / (1 - sum_sqs_val);
142 x.adj().coeffRef(i, 0) += 2 * sum_sqs_adj * x.val().coeff(i, 0);
144 z.adj().coeffRef(k) += x.adj().coeffRef(i, 0);
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)
Eigen::Matrix< value_type_t< EigVec >, Eigen::Dynamic, Eigen::Dynamic > cholesky_corr_constrain(const EigVec &y, int K)
plain_type_t< T > corr_constrain(const T &x)
Return the result of transforming the specified scalar or container of values to have a valid correla...
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.
fvar< T > log1m(const fvar< T > &x)
fvar< T > square(const fvar< T > &x)
typename scalar_type< T >::type scalar_type_t
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 ...