feat(cgal): propagate Newton status + conditioning diagnostics into CGAL results
Follow-up to S2: surface the new NewtonResult diagnostics through the public CGAL result types so callers of the high-level API see them too. - Add `CGAL::Newton_status` (alias of conformallab::NewtonStatus) and three fields — `status`, `sparse_qr_fallback_used`, `min_ldlt_pivot` — to Conformal_map_result, Hyper_ideal_map_result and Circle_packing_result. (sparse_qr_fallback_used already existed on Conformal_map_result but was never populated; it is now wired through.) - Map them from NewtonResult at all five entry points (euclidean / spherical / hyper_ideal / inversive_distance / cp_euclidean). - Test: SingleTriangleConverges now asserts status == Converged and the diagnostics propagate. Additive only — existing `converged`/`iterations`/`gradient_norm` semantics unchanged. 301/301 CGAL tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -78,6 +78,10 @@ namespace CGAL {
|
||||
// Result type
|
||||
// ════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
/// Why the Newton solve terminated (re-exported from the solver; I1 audit).
|
||||
/// `Converged` / `MaxIterations` / `LinearSolverFailed` / `LineSearchStalled`.
|
||||
using Newton_status = ::conformallab::NewtonStatus;
|
||||
|
||||
/*!
|
||||
\ingroup PkgConformalMapRef
|
||||
|
||||
@@ -100,9 +104,18 @@ struct Conformal_map_result
|
||||
/// `true` iff `gradient_norm < gradient_tolerance`.
|
||||
bool converged = false;
|
||||
|
||||
/// Why the solve stopped (more informative than `converged` alone): one of
|
||||
/// `Converged` / `MaxIterations` / `LinearSolverFailed` / `LineSearchStalled`.
|
||||
Newton_status status = Newton_status::MaxIterations;
|
||||
|
||||
/// `true` iff the linear solver used the SparseQR fallback at any
|
||||
/// Newton step (gauge mode on closed mesh without pinned vertex).
|
||||
bool sparse_qr_fallback_used = false;
|
||||
|
||||
/// Smallest `|Dᵢᵢ|` of the last LDLT factorisation — a cheap
|
||||
/// near-singularity proxy (small ⇒ ill-conditioned solve). `0` if LDLT
|
||||
/// never succeeded.
|
||||
FT min_ldlt_pivot = FT(0);
|
||||
};
|
||||
|
||||
|
||||
@@ -272,6 +285,9 @@ auto discrete_conformal_map_euclidean(
|
||||
result.iterations = nr.iterations;
|
||||
result.gradient_norm = nr.grad_inf_norm;
|
||||
result.converged = nr.converged;
|
||||
result.status = nr.status;
|
||||
result.sparse_qr_fallback_used = nr.sparse_qr_fallback_used;
|
||||
result.min_ldlt_pivot = static_cast<FT>(nr.min_ldlt_pivot);
|
||||
|
||||
// ── 8. Optional layout step (Phase 8b-Lite extension) ──────────────────
|
||||
//
|
||||
@@ -410,6 +426,9 @@ auto discrete_conformal_map_spherical(
|
||||
result.iterations = nr.iterations;
|
||||
result.gradient_norm = nr.grad_inf_norm;
|
||||
result.converged = nr.converged;
|
||||
result.status = nr.status;
|
||||
result.sparse_qr_fallback_used = nr.sparse_qr_fallback_used;
|
||||
result.min_ldlt_pivot = static_cast<FT>(nr.min_ldlt_pivot);
|
||||
|
||||
// Optional 3-D layout step (point on S²)
|
||||
auto uv_param = parameters::get_parameter(
|
||||
@@ -459,6 +478,14 @@ struct Hyper_ideal_map_result
|
||||
FT gradient_norm = FT(0);
|
||||
/// `true` iff `gradient_norm < gradient_tolerance` at exit.
|
||||
bool converged = false;
|
||||
|
||||
/// Why the solve stopped: `Converged` / `MaxIterations` /
|
||||
/// `LinearSolverFailed` / `LineSearchStalled`.
|
||||
Newton_status status = Newton_status::MaxIterations;
|
||||
/// `true` iff any Newton step fell back to SparseQR (gauge singularity).
|
||||
bool sparse_qr_fallback_used = false;
|
||||
/// Smallest `|Dᵢᵢ|` of the last LDLT (near-singularity proxy; 0 if none).
|
||||
FT min_ldlt_pivot = FT(0);
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -538,6 +565,9 @@ auto discrete_conformal_map_hyper_ideal(
|
||||
result.iterations = nr.iterations;
|
||||
result.gradient_norm = nr.grad_inf_norm;
|
||||
result.converged = nr.converged;
|
||||
result.status = nr.status;
|
||||
result.sparse_qr_fallback_used = nr.sparse_qr_fallback_used;
|
||||
result.min_ldlt_pivot = static_cast<FT>(nr.min_ldlt_pivot);
|
||||
|
||||
// Optional Poincaré-disk layout (2-D in the unit disk).
|
||||
auto uv_param = parameters::get_parameter(
|
||||
|
||||
Reference in New Issue
Block a user