Fix dense Cholesky refinement residual storage DenseCholesky accepts a column-major lower triangle. Map that storage explicitly and use its lower self-adjoint view for refinement residuals. Poison unused triangles in the existing backend and size tests. Compute the right-hand side before poisoning the input. Direct refiner tests retain a full-matrix reference and factorization. Preserve tolerances and iteration limits. Issue: https://github.com/ceres-solver/ceres-solver/issues/863 Codex used. Change-Id: I06d272ac382de5aecd6805a02d5f9c996aa88a4f
diff --git a/internal/ceres/dense_cholesky_test.cc b/internal/ceres/dense_cholesky_test.cc index ac5075a..b5fa59b 100644 --- a/internal/ceres/dense_cholesky_test.cc +++ b/internal/ceres/dense_cholesky_test.cc
@@ -99,6 +99,7 @@ lhs += VectorType::Ones(num_cols).asDiagonal(); Vector x = VectorType::Random(num_cols); Vector rhs = lhs * x; + lhs.triangularView<Eigen::StrictlyUpper>().setZero(); Vector actual = Vector::Random(num_cols); LinearSolver::Summary summary;
diff --git a/internal/ceres/iterative_refiner.cc b/internal/ceres/iterative_refiner.cc index 54d48f3..da3cc15 100644 --- a/internal/ceres/iterative_refiner.cc +++ b/internal/ceres/iterative_refiner.cc
@@ -86,12 +86,12 @@ DenseCholesky* cholesky, double* solution_ptr) { Allocate(num_cols); - ConstMatrixRef lhs(lhs_ptr, num_cols, num_cols); + Eigen::Map<const Eigen::MatrixXd> lhs(lhs_ptr, num_cols, num_cols); ConstVectorRef rhs(rhs_ptr, num_cols); VectorRef solution(solution_ptr, num_cols); std::string ignored_message; for (int i = 0; i < max_num_iterations_; ++i) { - residual_ = rhs - lhs * solution; + residual_ = rhs - lhs.selfadjointView<Eigen::Lower>() * solution; // solution += lhs^-1 residual cholesky->Solve(residual_.data(), correction_.data(), &ignored_message); solution += correction_;
diff --git a/internal/ceres/iterative_refiner_test.cc b/internal/ceres/iterative_refiner_test.cc index a2557f2..ffa25dc 100644 --- a/internal/ceres/iterative_refiner_test.cc +++ b/internal/ceres/iterative_refiner_test.cc
@@ -45,8 +45,10 @@ // Macros to help us define virtual methods which we do not expect to // use/call in this test. -#define DO_NOT_CALL \ - { LOG(FATAL) << "DO NOT CALL"; } +#define DO_NOT_CALL \ + { \ + LOG(FATAL) << "DO NOT CALL"; \ + } #define DO_NOT_CALL_WITH_RETURN(x) \ { \ LOG(FATAL) << "DO NOT CALL"; \ @@ -219,6 +221,7 @@ RandomSolutionWithExactFactorizationConverges) { Matrix lhs = lhs_; FakeDenseCholesky<double> dense_cholesky(lhs); + lhs.triangularView<Eigen::StrictlyLower>().setZero(); DenseIterativeRefiner refiner(max_num_iterations_); Vector refined_solution(num_cols_); refined_solution.setRandom(); @@ -238,6 +241,7 @@ // Use a single precision Cholesky factorization of the double // precision matrix. This will give us an approximate factorization. FakeDenseCholesky<float> dense_cholesky(lhs_); + lhs.triangularView<Eigen::StrictlyLower>().setZero(); DenseIterativeRefiner refiner(max_num_iterations_); Vector refined_solution(num_cols_); refined_solution.setRandom();