1 #ifndef STAN_MATH_PRIM_FUN_CHOLESKY_CORR_FREE_HPP
2 #define STAN_MATH_PRIM_FUN_CHOLESKY_CORR_FREE_HPP
3
4 #include <stan/math/prim/err.hpp>
5 #include <stan/math/prim/fun/Eigen.hpp>
6 #include <stan/math/prim/fun/corr_free.hpp>
7 #include <stan/math/prim/fun/square.hpp>
8 #include <cmath>
9
10 namespace stan {
11 namespace math {
12
13 template <typename T, require_eigen_t<T>* = nullptr>
cholesky_corr_free(const T & x)14 auto cholesky_corr_free(const T& x) {
15 using Eigen::Dynamic;
16 using Eigen::Matrix;
17
18 check_square("cholesky_corr_free", "x", x);
19 // should validate lower-triangular, unit lengths
20
21 const auto& x_ref = to_ref(x);
22 int K = (x.rows() * (x.rows() - 1)) / 2;
23 Matrix<value_type_t<T>, Dynamic, 1> z(K);
24 int k = 0;
25 for (int i = 1; i < x.rows(); ++i) {
26 z.coeffRef(k++) = corr_free(x_ref.coeff(i, 0));
27 double sum_sqs = square(x_ref.coeff(i, 0));
28 for (int j = 1; j < i; ++j) {
29 z.coeffRef(k++) = corr_free(x_ref.coeff(i, j) / std::sqrt(1.0 - sum_sqs));
30 sum_sqs += square(x_ref.coeff(i, j));
31 }
32 }
33 return z;
34 }
35
36 /**
37 * Overload of `cholesky_corr_free()` to untransform each matrix
38 * in a standard vector.
39 * @tparam T A standard vector with with a `value_type` which inherits from
40 * `Eigen::MatrixBase`.
41 * @param x The standard vector to untransform.
42 */
43 template <typename T, require_std_vector_t<T>* = nullptr>
cholesky_corr_free(const T & x)44 auto cholesky_corr_free(const T& x) {
45 return apply_vector_unary<T>::apply(
46 x, [](auto&& v) { return cholesky_corr_free(v); });
47 }
48
49 } // namespace math
50 } // namespace stan
51 #endif
52