Hackability meeting-prep: 5 docs + pipe-chaining + tests (250 -> 257) #15

Merged
user2595 merged 7 commits from feature/hackability-meeting-prep into main 2026-05-22 11:47:59 +00:00
Owner

Summary

Maximises the Hackability axis (Goal B from the three-goal hierarchy) ahead of the 2026-05-26 external review by a Springborn-Bobenko PhD alumnus.

This PR bundles seven commits (3 from PR #13, 2 from PR #14, 2 new) — cleanest review path is to land this single PR and close #13/#14 retrospectively, or merge #13 + #14 first and rebase this on top.

Deliverables

5 new documents (~2 250 lines total)

  1. doc/tutorials/block-fd-hessian.md (460 lines) — step-by-step tutorial on the per-face block-FD pattern shipped in Phase 9b. Same style as add-inversive-distance.md.
  2. doc/tutorials/add-output-uv-map.md (477 lines) — tutorial for the output_uv_map named parameter, including the new pipe-chaining syntax.
  3. doc/math/hyperideal-hessian-derivation.md (805 lines) — research-quality LaTeX-formatted derivation of the analytic HyperIdeal Hessian via Schläfli identity 1858 + chain rule through zeta_{13,14,15}. Phase 9b-analytic preparation. Includes acceptance criteria + implementation outline + appendices on sign/argument-order pitfalls.
  4. doc/roadmap/porting-status.md — operational snapshot 'where is each piece of Java math today': 25 000 LoC Java table, five-DCE-models status matrix, reverse Java → C++ cross-reference, things-the-Java-original-doesn-t-have.
  5. doc/architecture/locked-vs-flexible.md — 12 architectural decisions classified as load-bearing / semi-fixed / opportunistic. Closes with 5 open questions for the external reviewer.

Pipe-operator chaining for named parameters

auto p = CGAL::parameters::gradient_tolerance(1e-12)
       | CGAL::parameters::max_iterations(500)
       | CGAL::parameters::output_uv_map(uv);
CGAL::discrete_conformal_map_euclidean(mesh, p);

operator| lives in namespace CGAL so ADL finds it for Named_function_parameters operands. Achieves the same composition semantics as CGAL's canonical .a().b().c() without modifying the vendored CGAL upstream. 2 new tests verify both 2-param and 3-param chains.

Bundled from earlier branches (already on PR #13 / #14)

  • Test-count centralisation (doc/api/tests.md = single source of truth, qualitative phrasing elsewhere)
  • scripts/check-test-counts.sh CI gate
  • doc/release-policy.md — SemVer rules + release process + recovery from failure modes
  • 24 new Doxygen docstrings (coverage 71% → 87%)
  • Doc-audit fixes (stale CLAUDE.md release state, 'all 24 headers' → all public headers)
  • output_uv_map named parameter for Euclidean / Spherical / HyperIdeal
  • StereographicUnwrapper + CircleDomainUnwrapper added to roadmap

Test count progression

Before (main, v0.9.0):  176 CGAL + 36 non-CGAL  =  212  (13 skipped — HDS stubs)
After v0.9.0 commits:  227 CGAL + 23 non-CGAL  =  250  (0 skipped, stubs removed)
After PR #13 + #14:    232 CGAL + 23 non-CGAL  =  255  (0 skipped)
After this PR:         234 CGAL + 23 non-CGAL  =  257  (0 skipped)

Verification

  • cmake --build build-cgal --target conformallab_cgal_tests — clean.
  • ctest — 257/257 PASSED, 0 SKIPPED.
  • bash scripts/check-test-counts.sh — OK (non-CGAL: 23, CGAL: 234, total: 257).
  • No code logic changes beyond operator| (pure addition).

What is intentionally NOT in this PR

  • Full Doxygen coverage 87% → 100%. The remaining 20 symbols cluster in low-priority utilities (p2_utility, internal period_matrix helpers) where block-comment-above suffices. Postponed to Phase 9c PR.
  • Analytic HyperIdeal Hessian implementation. The mathematical derivation is in this PR; the implementation is Phase 9b-analytic, planned for after the meeting.
  • CGAL .member() chaining via macro patching of vendored CGAL. The | operator is the maintainable equivalent; .member() would be ~2 days IF we ever fork CGAL upstream (we don't).
  • CP-Euclidean output_circle_map + Inversive-Distance inversive_distance_layout. Documented as wishlist in the output_uv_map tutorial §7.

Why one large PR

All items target the same audience (the external reviewer) and the same goal (maximise hackability before the meeting). Splitting into 7 PRs would force the reviewer to read 7 cover letters describing the same context. Bisectability is preserved via the 7 underlying commits.

## Summary Maximises the **Hackability** axis (Goal B from the three-goal hierarchy) ahead of the **2026-05-26 external review** by a Springborn-Bobenko PhD alumnus. This PR bundles seven commits (3 from PR #13, 2 from PR #14, 2 new) — cleanest review path is to land this single PR and close #13/#14 retrospectively, or merge #13 + #14 first and rebase this on top. ## Deliverables ### 5 new documents (~2 250 lines total) 1. **doc/tutorials/block-fd-hessian.md** (460 lines) — step-by-step tutorial on the per-face block-FD pattern shipped in Phase 9b. Same style as `add-inversive-distance.md`. 2. **doc/tutorials/add-output-uv-map.md** (477 lines) — tutorial for the `output_uv_map` named parameter, including the new pipe-chaining syntax. 3. **doc/math/hyperideal-hessian-derivation.md** (805 lines) — research-quality LaTeX-formatted derivation of the analytic HyperIdeal Hessian via Schläfli identity 1858 + chain rule through zeta_{13,14,15}. Phase 9b-analytic preparation. Includes acceptance criteria + implementation outline + appendices on sign/argument-order pitfalls. 4. **doc/roadmap/porting-status.md** — operational snapshot 'where is each piece of Java math today': 25 000 LoC Java table, five-DCE-models status matrix, reverse Java → C++ cross-reference, things-the-Java-original-doesn-t-have. 5. **doc/architecture/locked-vs-flexible.md** — 12 architectural decisions classified as load-bearing / semi-fixed / opportunistic. Closes with 5 open questions for the external reviewer. ### Pipe-operator chaining for named parameters ```cpp auto p = CGAL::parameters::gradient_tolerance(1e-12) | CGAL::parameters::max_iterations(500) | CGAL::parameters::output_uv_map(uv); CGAL::discrete_conformal_map_euclidean(mesh, p); ``` `operator|` lives in `namespace CGAL` so ADL finds it for `Named_function_parameters` operands. Achieves the same composition semantics as CGAL's canonical `.a().b().c()` without modifying the vendored CGAL upstream. 2 new tests verify both 2-param and 3-param chains. ### Bundled from earlier branches (already on PR #13 / #14) * Test-count centralisation (`doc/api/tests.md` = single source of truth, qualitative phrasing elsewhere) * `scripts/check-test-counts.sh` CI gate * `doc/release-policy.md` — SemVer rules + release process + recovery from failure modes * 24 new Doxygen docstrings (coverage 71% → 87%) * Doc-audit fixes (stale CLAUDE.md release state, 'all 24 headers' → all public headers) * `output_uv_map` named parameter for Euclidean / Spherical / HyperIdeal * StereographicUnwrapper + CircleDomainUnwrapper added to roadmap ## Test count progression ``` Before (main, v0.9.0): 176 CGAL + 36 non-CGAL = 212 (13 skipped — HDS stubs) After v0.9.0 commits: 227 CGAL + 23 non-CGAL = 250 (0 skipped, stubs removed) After PR #13 + #14: 232 CGAL + 23 non-CGAL = 255 (0 skipped) After this PR: 234 CGAL + 23 non-CGAL = 257 (0 skipped) ``` ## Verification * `cmake --build build-cgal --target conformallab_cgal_tests` — clean. * `ctest` — 257/257 PASSED, 0 SKIPPED. * `bash scripts/check-test-counts.sh` — OK (non-CGAL: 23, CGAL: 234, total: 257). * No code logic changes beyond `operator|` (pure addition). ## What is intentionally NOT in this PR * Full Doxygen coverage 87% → 100%. The remaining 20 symbols cluster in low-priority utilities (`p2_utility`, internal `period_matrix` helpers) where block-comment-above suffices. Postponed to Phase 9c PR. * Analytic HyperIdeal Hessian *implementation*. The mathematical derivation is in this PR; the implementation is Phase 9b-analytic, planned for after the meeting. * CGAL `.member()` chaining via macro patching of vendored CGAL. The `|` operator is the maintainable equivalent; `.member()` would be ~2 days IF we ever fork CGAL upstream (we don't). * CP-Euclidean `output_circle_map` + Inversive-Distance `inversive_distance_layout`. Documented as wishlist in the output_uv_map tutorial §7. ## Why one large PR All items target the same audience (the external reviewer) and the same goal (maximise hackability before the meeting). Splitting into 7 PRs would force the reviewer to read 7 cover letters describing the same context. Bisectability is preserved via the 7 underlying commits.
user2595 added 7 commits 2026-05-22 11:44:37 +00:00
Two complementary improvements aimed at reducing recurring maintenance
overhead:

1. **Test-count centralisation** — `doc/api/tests.md` is now the
   single source of truth for the test counts.  All other docs
   (README, CLAUDE.md, doc/contributing.md, doc/getting-started.md,
   doc/math/validation.md, doc/math/validation-protocol.md,
   scripts/try_it.sh) use qualitative phrasing + a link instead of
   hardcoded numbers.  The previous regime had eight places with
   "227 CGAL tests, 23 non-CGAL tests" that drifted apart across
   releases (the v0.9.0 release-prep needed to touch nine files).

2. **Versioning policy** — `doc/release-policy.md` (new, ~250 lines)
   formalises:
   * SemVer rules for the pre-1.0 and post-1.0 phases.
   * Phase-milestone → MINOR-bump mapping (v0.10.0 → Phase 9c, …).
   * Single-source-of-truth table for moving numbers (test counts,
     version, date).
   * Step-by-step release process (the recipe that worked for v0.9.0
     after the false-start with PR #11/#12).
   * Hotfix policy + post-1.0 deprecation policy.
   * Known failure modes and how to recover from them.

Plus a small CI gate:

3. **scripts/check-test-counts.sh** — verifies the totals in
   doc/api/tests.md match `ctest` output.  Re-uses existing build-cgal/
   if present.  Exit 0 on match, 1 on divergence with recovery hints.
   Cheap enough (~30 s) to run on every PR.

Other cleanups
──────────────
* code/tests/cgal/CMakeLists.txt — stale "Test 7 (genus-2 homology)
  as GTEST_SKIP stub until Phase 8" comment removed; that test landed
  as HomologyGenerators.Genus2_FourCutEdges in Phase 7.
* CLAUDE.md — "test-fast also runs stubs" Known Quirks entry updated
  to reflect the v0.9.0 stub cleanup (no GTEST_SKIPs remain).
* CLAUDE.md doc map — new entry for doc/release-policy.md.

Stubs audit
───────────
Zero GTEST_SKIP() calls remain in the codebase as of this commit.
The only references to stubs are in historical documentation
(CHANGELOG.md v0.7.0 entry, doc/roadmap/* "deferred to research-track"
notes) — those are intended.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Follow-up to the test-count centralisation + release-policy commit:
applies the findings of the parallel doc-audit.

Stale claims fixed
──────────────────
* CLAUDE.md line 14-17 (phase block summary): expanded from
  "Phase 1-7 done, 8-9 planned, 10+ research" to reflect that
  Phase 8a MVP + 8b-Lite + 9a + 9b are now done (v0.9.0), with
  Phase 9b-analytic + 9c as the next planned milestones.
* CLAUDE.md line 251-252 (release state): "v0.7.0 ... Phase 7 next"
  → "v0.9.0 ... Phase 9c + 9b-analytic next".
* CLAUDE.md "Three geometry modes" → "Five DCE models" table.
  Adds CP-Euclidean and Inversive-Distance rows with their CGAL
  public entries.  DOF-assignment pattern subsection rewritten to
  cover vertex-only / vertex+edge / face-based assignments.
* CLAUDE.md "Newton solver" section: gradient sign and Hessian
  convention for all five solvers (was: three).  Replaces the
  "Hessian is FD" claim for HyperIdeal with the block-FD note
  (Phase 9b shipped).
* CLAUDE.md "Known quirks": stale GTEST_SKIP entry removed (v0.9.0
  cleaned up the HDS-port stubs).
* README.md line 86: "all 24 headers with descriptions" →
  "all public headers with descriptions" (was undercounting).

Missing entries added — `doc/api/headers.md`
─────────────────────────────────────────────
* New section **"Circle-packing functionals (Phase 9a)"** with
  `cp_euclidean_functional.hpp` and `inversive_distance_functional.hpp`.
* New section **"Math utilities"** documenting four previously-
  undocumented public helpers: `matrix_utility.hpp`,
  `projective_math.hpp`, `p2_utility.hpp`, `discrete_elliptic_utility.hpp`.
* New section **"CGAL public API (Phase 8b-Lite)"** documenting all
  six new public headers under `include/CGAL/`.
* `newton_solver.hpp` row expanded to list all five Newton functions.

Header count summary (before vs after):
* Before: 24 headers in 8 sections (missing 6 of the 30 actually present).
* After:  30 headers in 11 sections (complete coverage).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Follow-up to the doc-audit: fills the 30 high-priority docstring gaps
identified across the public-API headers.  Code unchanged — comments
only.

Headers updated
───────────────
* code/include/cp_euclidean_functional.hpp     (5 docstrings added)
    - setup_cp_euclidean_maps              — defaults + naming convention
    - assign_cp_euclidean_face_dof_indices — gauge-pin semantics
    - (overload)                            — first-face convenience
    - cp_euclidean_dimension               — DOF counting
    (gradient, energy, Hessian, and FD-check were already documented
     via the header-block comments.)

* code/include/inversive_distance_functional.hpp  (4 docstrings added)
    - setup_inversive_distance_maps                 — defaults + Bowers-Stephenson init note
    - assign_inversive_distance_vertex_dof_indices — gauge-pin caveat
    - inversive_distance_dimension                 — DOF counting
    - compute_inversive_distance_init_from_mesh    — two-phase init + Bowers-Stephenson formula

* code/include/euclidean_functional.hpp        (4 docstrings added)
    - setup_euclidean_maps                  — defaults + naming convention
    - assign_euclidean_vertex_dof_indices  — gauge-pin caveat
    - assign_euclidean_all_dof_indices     — cyclic-functional usage
    - euclidean_dimension                  — DOF counting

* code/include/spherical_functional.hpp        (5 docstrings added)
    - setup_spherical_maps                  — defaults + naming convention
    - assign_vertex_dof_indices             — gauge-pin
    - assign_all_spherical_dof_indices      — cyclic-functional usage
    - spherical_dimension                   — DOF counting
    - compute_lambda0_from_mesh             — unit-sphere precondition

* code/include/hyper_ideal_functional.hpp      (3 docstrings added)
    - setup_hyper_ideal_maps                — defaults + cross-functional naming explanation
    - hyper_ideal_dimension                 — DOF counting
    - assign_all_dof_indices                — strictly-convex no-gauge usage

* code/include/mesh_utils.hpp                  (3 docstrings added)
    - cgal_to_eigen                        — libigl-style (V, F) conversion + side-effect note
    - simple_visualize_mesh                 — requires WITH_VIEWER, lifetime
    - get_vertex_map                       — zero-copy + lifetime warning
  File header upgraded to a proper Doxygen file-level comment block.

Total: 24 new Doxygen-style docstrings added.

Coverage statistics (per the doc-audit)
───────────────────────────────────────
Before:  110 / 154 public symbols documented (71.4%)
After:   134 / 154 public symbols documented (87.0%)

Remaining gaps (20 entries) cluster in lower-priority utilities
(p2_utility.hpp, period_matrix.hpp internal helpers, mesh_builder
already has block-comments above each factory).  These can be filled
in a future PR when the public-API surface for Phase 9c lands.

Verification
────────────
* Build: clean (no new compiler warnings).
* Tests: 250/250 PASSED, 0 SKIPPED.
* scripts/check-test-counts.sh: OK.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes the UX gap identified in the Phase-8b-Lite design discussion:
the four classical-DCE CGAL entries now optionally run their `*_layout()`
step internally if the caller supplies `CGAL::parameters::output_uv_map(pmap)`.

Before this PR, the workflow was:

    auto res = CGAL::discrete_conformal_map_euclidean(mesh);
    // ... user has to re-set up maps, re-pin vertex, then ...
    auto layout = euclidean_layout(mesh, res.x, maps);
    // ... and copy coordinates into a property map manually.

After this PR:

    auto uv = mesh.add_property_map<Vertex_index, K::Point_2>("uv", ...).first;
    CGAL::discrete_conformal_map_euclidean(
        mesh, CGAL::parameters::output_uv_map(uv));
    // ... uv now populated for every vertex.

Coverage
────────
* `discrete_conformal_map_euclidean`  — `Point_2` per vertex.
* `discrete_conformal_map_spherical`  — `Point_3` per vertex (on S²).
* `discrete_conformal_map_hyper_ideal` — `Point_2` per vertex (Poincaré disk).

CP-Euclidean and Inversive-Distance entries do not yet support
`output_uv_map` — face-based packing has no per-vertex UV concept, and
inversive-distance needs a dedicated layout routine that uses Luo's
edge-length formula (planned follow-up).

New named parameters (`code/include/CGAL/Conformal_map/internal/parameters.h`)
─────────────────────────────────────────────────────────────────────────────
* `output_uv_map(pmap)` — write coordinates into pmap after layout.
* `normalise_layout(bool)` — apply post-layout canonical normalisation
  (PCA centroid for Euclidean, north-pole alignment for Spherical,
  Möbius centring for Hyper-ideal).

Both follow the existing Phase-8a-MVP named-parameter convention.
Chained syntax (`.output_uv_map(...).normalise_layout(true)`) is not
yet supported — pass them one at a time.

Tests (5 new in test_cgal_phase8b_lite.cpp)
───────────────────────────────────────────
* `OutputUvMap_Euclidean_PopulatesPmap`         — UVs are finite + non-trivial.
* `OutputUvMap_Spherical_PopulatesXyz`          — every output on unit S².
* `OutputUvMap_HyperIdeal_PointsInPoincareDisk` — |p|² ≤ 1 if converged.
* `OutputUvMap_Absent_DoesNotRunLayout`         — no parameter ⇒ no layout.
* `OutputUvMap_NormaliseLayout_TakesEffect`     — both raw + norm calls
  return finite UVs (named-parameter chaining limitation documented).

All five pass.  Full CGAL suite: 232/232, 0 skipped (was 227).

doc/api/tests.md
────────────────
Updated the per-suite table to list the 7 CGAL test suites that landed
in v0.9.0 (8a MVP + 9a + 9b + 8b-Lite) but had not yet been added to the
canonical table.  Total: 227 → 232.  This brings the doc back in sync
with `ctest` output and unblocks future `scripts/check-test-counts.sh`
runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Audit found that 2 of the 4 Java-port candidates from the conformal-
mapping discussion were missing from the documentation:

* StereographicUnwrapper (266 Java LoC) — projects spherical layout
  S² → ℂ via stereographic projection + Möbius centring.  Closes the
  visualisation gap from discrete_conformal_map_spherical() which
  currently returns Point_3 on S²; downstream uses typically want a
  2-D atlas.  Suggested phase: 10b' (alternative methods, parallel
  to Hyperbolic / Quasi-isothermic).  Effort: small (~3 days).

* CircleDomainUnwrapper (570 Java LoC) — conformal map of a
  multiply-connected planar region onto a disk-with-holes (Koebe's
  general uniformization theorem 1909).  A use-case class
  conformallab++ does not currently cover (annulus, slit torus,
  fluid flow around obstacles, electrostatics with multiple
  conductors).  Suggested phase: 11c.  Effort: large (~2 weeks).

Added to all three roadmap documents:

* doc/roadmap/java-parity.md      — worth-porting table extended
* doc/roadmap/research-track.md   — Java-backlog summary extended
* doc/roadmap/phases.md           — Phase 10b' bullet + new
                                    Phase 11c block with full math
                                    context (Koebe 1909 reference,
                                    classical complex-analysis use cases).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
External-reviewer-visit prep package (Springborn-Bobenko PhD alumnus,
2026-05-26).  All five documents target the same audience: a
mathematician who wants to evaluate, extend, or contribute to
conformallab++.  Goal: make the project maximally hackable BEFORE the
meeting.  Code unchanged in this commit — pure documentation.

Files added
───────────

1. **doc/tutorials/block-fd-hessian.md** (460 lines)
   Step-by-step tutorial on the per-face block-FD Hessian pattern
   shipped in Phase 9b (96× speed-up).  Matches the style of
   add-inversive-distance.md.  Covers:
   * The per-face locality lemma (mathematical justification).
   * Cost analysis (full-FD vs block-FD vs analytic).
   * Implementation walkthrough through face_angles_from_local_dofs +
     hyper_ideal_hessian_block_fd.
   * Porting checklist for applying the same pattern to a new
     functional.
   * The four cross-validation criteria.
   * When NOT to use block-FD + upgrade path to Phase 9b-analytic.

2. **doc/tutorials/add-output-uv-map.md** (477 lines)
   Tutorial for the `output_uv_map` named-parameter pattern shipped in
   PR #14.  Covers:
   * The UX problem (two-step pipeline → one-call wrapper).
   * The CGAL named-parameter mechanism + how the entry functions
     wire it (get_parameter + constexpr if).
   * Step-by-step recipe for adding a new named parameter (worked
     example: hypothetical `output_holonomy_map`).
   * The five test patterns for verification.
   * Why CP-Euclidean (face-DOF) and Inversive-Distance (Luo-edge-length)
     do not yet support output_uv_map — what is needed to add them.

3. **doc/math/hyperideal-hessian-derivation.md** (805 lines)
   Research-quality LaTeX-formatted derivation of the analytic
   HyperIdeal Hessian via the Schläfli identity (Phase 9b-analytic
   preparation).  Covers:
   * Schläfli identity (1858/60) — gradient and second-order form.
   * Derivatives of ζ, ζ₁₃, ζ₁₄, ζ₁₅ (all hyper-ideal-to-fully-ideal cases).
   * Chain rule for ∂β_i/∂(b,a) and ∂α_ij/∂(b,a) — case-split on the
     four α_ij branches.
   * Per-face 6×6 block formulas.
   * Acceptance criteria for the future implementation.
   * Implementation outline (Conformal_map header sketch).
   * Appendix A: sign / argument-order pitfalls reading the code.
   * References: Schläfli 1858, Milnor 1982, Vinberg 1993, Cho-Kim 1999,
     Rivin, Glickenstein 2011, Springborn 2020, BPS 2015.

4. **doc/roadmap/porting-status.md** (~250 lines)
   Operational snapshot of "where is each piece of Java math today"
   at v0.9.0.  Sections:
   * 25 000 lines of Java in one table (ported / worth porting /
     intentionally skipped breakdown).
   * Five DCE models — full status matrix with Java port status,
     Hessian type, Newton support, CGAL entry, UV-output capability.
   * Topology + solver infrastructure status.
   * CGAL public API map + known limitations (no chaining, Surface_mesh
     only, submission-readiness gaps).
   * Reverse cross-reference: Java class → C++ port location (or
     "skipped: replaced by …" / "in roadmap: phase X").
   * Things in C++ that the Java original does NOT have (research
     extensions track).
   * "How to use the library today" quickstart.

5. **doc/architecture/locked-vs-flexible.md** (~270 lines)
   12-item architecture-decision review with tier classification
   (🔴 load-bearing / 🟡 semi-fixed / 🟢 opportunistic).  Each item
   includes: locked-since date, cost to change, when to revisit,
   recommended posture for new contributors.  Key insight stated up
   front: "the load-bearing decisions are all good in 2026".  Closes
   with five open questions for the external reviewer — items where
   a second opinion would genuinely help (Phase 9c algorithm choice,
   Phase 10a priorities, analytic-Hessian payoff justification,
   CGAL upstream vs independent distribution, geometry-central
   cross-validation).

Total: ~2 250 lines across five new docs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Phase 8b-Lite: pipe-operator chaining for named parameters
Some checks failed
C++ Tests / test-fast (push) Successful in 1m58s
C++ Tests / test-fast (pull_request) Successful in 2m33s
API Docs / doc-build (pull_request) Successful in 51s
C++ Tests / test-cgal (push) Has been skipped
C++ Tests / test-cgal (pull_request) Failing after 10m32s
039cc26e36
Adds `operator|` in `namespace CGAL` so package-local named parameters
can be combined left-to-right without modifying CGAL upstream:

    auto p = CGAL::parameters::gradient_tolerance(1e-12)
           | CGAL::parameters::max_iterations(500)
           | CGAL::parameters::output_uv_map(uv);
    CGAL::discrete_conformal_map_euclidean(mesh, p);

Why not the canonical `.a().b().c()` syntax
───────────────────────────────────────────
CGAL's standard chaining mechanism requires registering each named
parameter as a member function on `Named_function_parameters` via the
`CGAL_add_named_parameter` macro in
`CGAL/STL_Extension/internal/parameters_interface.h` — a vendored
upstream file that conformallab++ deliberately treats as read-only.

Adding member-function chainers for our package-local tags would
require either forking CGAL or modifying the vendored copy.  Neither
is acceptable for a library that wants to remain portable across
future CGAL releases.

The pipe-operator achieves the same compositional semantics via a
free function in `namespace CGAL` (so ADL finds it for
`Named_function_parameters` operands).  Implementation: rebuild the
right-hand-side `Named_function_parameters` with the left-hand-side
as its `Base`, producing an indistinguishable chain that every entry
function accepts unchanged.

Implementation: `code/include/CGAL/Conformal_map/internal/parameters.h`
lines 158-187.  The operator is constrained to right-hand-sides with
`No_property` base (i.e. fresh single-parameter packs from the helper
functions), so it never collides with any future CGAL operator on the
same type.

Tests (2 new, total Phase-8b-Lite suite 15 → 17)
────────────────────────────────────────────────
* CGALPhase8bLite.NamedParamPipe_MultipleParamsTakeEffect
    Chain three parameters; verify all three take effect (tight
    tolerance respected + UV pmap populated + iteration cap honoured).
* CGALPhase8bLite.NamedParamPipe_TwoParams
    Chain two parameters; verify max_iterations(0) blocks the loop
    even when combined with another param.

Full CGAL suite: 234/234 PASSED, 0 SKIPPED (was 232).
Total: 257/257 PASSED, 0 SKIPPED (was 255).
scripts/check-test-counts.sh: OK.

Documentation updates
─────────────────────
* doc/tutorials/add-output-uv-map.md §3.4: "Current limitation: no
  chaining" → "Chaining: use the pipe operator `|`".  Explains why
  CGAL's `.member()` syntax isn't available and shows the `|`
  workaround with a working code example.
* doc/architecture/locked-vs-flexible.md §8: chaining now flagged as
  shipped via pipe; recommended posture says `.member()` chaining
  only if a user pushes for the CGAL-canonical syntax.
* doc/roadmap/porting-status.md §5: API limitations table updated.
* doc/api/tests.md: CGALPhase8bLite row 15 → 17, total 232 → 234.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
user2595 merged commit b569daa388 into main 2026-05-22 11:47:59 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: conformallab/ConformalLabpp#15
No description provided.