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