void factor_U(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& U, Eigen::Array<T, Eigen::Dynamic, 1>& CPCs) { size_t K = U.rows(); size_t position = 0; size_t pull = K - 1; if (K == 2) { CPCs(0) = atanh(U(0, 1)); return; } Eigen::Array<T, 1, Eigen::Dynamic> temp = U.row(0).tail(pull); CPCs.head(pull) = temp; Eigen::Array<T, Eigen::Dynamic, 1> acc(K); acc(0) = -0.0; acc.tail(pull) = 1.0 - temp.square(); for (size_t i = 1; i < (K - 1); i++) { position += pull; pull--; temp = U.row(i).tail(pull); temp /= sqrt(acc.tail(pull) / acc(i)); CPCs.segment(position, pull) = temp; acc.tail(pull) *= 1.0 - temp.square(); } CPCs = 0.5 * ( (1.0 + CPCs) / (1.0 - CPCs) ).log(); // now unbounded }
Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> read_corr_L(const Eigen::Array<T, Eigen::Dynamic, 1>& CPCs, // on (-1, 1) size_t K) { Eigen::Array<T, Eigen::Dynamic, 1> temp; Eigen::Array<T, Eigen::Dynamic, 1> acc(K-1); acc.setOnes(); // Cholesky factor of correlation matrix Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic> L(K, K); L.setZero(); size_t position = 0; size_t pull = K - 1; L(0, 0) = 1.0; L.col(0).tail(pull) = temp = CPCs.head(pull); acc.tail(pull) = T(1.0) - temp.square(); for (size_t i = 1; i < (K - 1); i++) { position += pull; pull--; temp = CPCs.segment(position, pull); L(i, i) = sqrt(acc(i-1)); L.col(i).tail(pull) = temp * acc.tail(pull).sqrt(); acc.tail(pull) *= T(1.0) - temp.square(); } L(K-1, K-1) = sqrt(acc(K-2)); return L.matrix(); }