cov_matrix_free() checks squareness, nonzero size, and a positive diagonal,
then consumes Eigen::LLT::matrixL() without checking llt.info(). A positive
diagonal does not make a matrix positive definite.
Minimal repro against develop at 344d7167a:
Eigen::MatrixXd bad(2, 2);
bad << 1.0, 2.0,
2.0, 1.0;
auto z = stan::math::cov_matrix_free(bad);
auto roundtrip = stan::math::cov_matrix_constrain(z, 2);
std::cout << z.transpose() << "\n"
<< (roundtrip - bad).cwiseAbs().maxCoeff() << "\n";
Actual result:
The inverse transform accepts an indefinite matrix and returns a finite vector
that reconstructs a different covariance matrix. The adjacent
cov_matrix_free_lkj() implementation already checks factorization success.
Check llt.info() == Eigen::Success before reading the factor, or use the
existing positive-definite validation seam. Add an indefinite positive-diagonal
case, a near-singular positive-definite case, and a valid round-trip case.
cov_matrix_free()checks squareness, nonzero size, and a positive diagonal,then consumes
Eigen::LLT::matrixL()without checkingllt.info(). A positivediagonal does not make a matrix positive definite.
Minimal repro against
developat344d7167a:Actual result:
The inverse transform accepts an indefinite matrix and returns a finite vector
that reconstructs a different covariance matrix. The adjacent
cov_matrix_free_lkj()implementation already checks factorization success.Check
llt.info() == Eigen::Successbefore reading the factor, or use theexisting positive-definite validation seam. Add an indefinite positive-diagonal
case, a near-singular positive-definite case, and a valid round-trip case.