From da591af8ff15e8685a2c54437a436c6265086eb3 Mon Sep 17 00:00:00 2001 From: Nick Thompson Date: Sat, 25 Jan 2025 14:55:00 -0800 Subject: [PATCH] Translate LAPACK exception codes to an actionable error message. --- mlx/backend/common/cholesky.cpp | 16 ++++++++++------ tests/linalg_tests.cpp | 4 ++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/mlx/backend/common/cholesky.cpp b/mlx/backend/common/cholesky.cpp index 62807e6dd9..7e1a9d2b39 100644 --- a/mlx/backend/common/cholesky.cpp +++ b/mlx/backend/common/cholesky.cpp @@ -41,13 +41,17 @@ void cholesky_impl(const array& a, array& factor, bool upper) { /* lda = */ &N, /* info = */ &info); - // TODO: We do nothing when the matrix is not positive semi-definite - // because throwing an error would result in a crash. If we figure out how - // to catch errors from the implementation we should throw. - if (info < 0) { + if (info != 0) { std::stringstream msg; - msg << "[cholesky] Cholesky decomposition failed with error code " - << info; + msg << "[cholesky] "; + // https://www.netlib.org/lapack/explore-html/d0/d18/group__ppsv_gab87078282c6c31853cfed4829976c0d9.html + if (info > 0) { + msg << "The leading principal minor of order " << info + << " of the matrix is not positive, so the factorization could not be completed."; + } else { + msg << "The " << -info + << " slot argument to the LAPACK Cholesky decomposition is invalid."; + } throw std::runtime_error(msg.str()); } diff --git a/tests/linalg_tests.cpp b/tests/linalg_tests.cpp index 352d16ff2c..5f0f0c7d0d 100644 --- a/tests/linalg_tests.cpp +++ b/tests/linalg_tests.cpp @@ -329,6 +329,10 @@ TEST_CASE("test matrix cholesky") { CHECK_THROWS(linalg::cholesky( array({1, 2, 3, 4, 5, 6}, {2, 3}), /* upper = */ false, Device::cpu)); + // Non-positive semi-definite throws. + CHECK_THROWS(linalg::cholesky( + array({1, 2}, {2, 1}), /* upper = */ false, Device::cpu)); + const auto prng_key = random::key(220398); const auto sqrtA = random::normal({5, 5}, prng_key); const auto A = matmul(sqrtA, transpose(sqrtA));