Skip to content

refactor(geometry)!: adopt la-stack 0.4.3 API (#424)#438

Merged
acgetchell merged 2 commits into
mainfrom
refactor/424-la-stack-api
Jun 9, 2026
Merged

refactor(geometry)!: adopt la-stack 0.4.3 API (#424)#438
acgetchell merged 2 commits into
mainfrom
refactor/424-la-stack-api

Conversation

@acgetchell

Copy link
Copy Markdown
Owner
  • Route stack-matrix dispatch, checked access, determinant filters, and singular tolerances through the local geometry matrix shim.
  • Preserve typed la-stack solve and factorization errors in geometry error paths instead of stringifying backend diagnostics.
  • Use rounded exact solve fallback for circumcenters and reject non-finite predicate matrices at construction boundaries.
  • Make .toroidal() the periodic image-point constructor and move wrapping-only construction to .canonicalized_toroidal().
  • Align pinned just, rumdl, taplo, dprint, and typos setup through cargo installs instead of Homebrew.
  • Disable la-stack default features explicitly while selecting exact arithmetic.

BREAKING CHANGE: .toroidal() now builds the periodic image-point quotient. Callers that only want coordinate wrapping must use .canonicalized_toroidal().

BREAKING CHANGE: .toroidal_periodic() has been removed.

BREAKING CHANGE: Error types that can carry la-stack diagnostics now implement PartialEq without Eq because la-stack 0.4.3 diagnostics can contain floating point payloads.

BREAKING CHANGE: geometry::matrix::SINGULARITY_TOLERANCE has been removed; singular solve tolerances are now owned by the la-stack shim.

Closes #424

- Route stack-matrix dispatch, checked access, determinant filters, and
  singular tolerances through the local geometry matrix shim.
- Preserve typed la-stack solve and factorization errors in geometry error paths
  instead of stringifying backend diagnostics.
- Use rounded exact solve fallback for circumcenters and reject non-finite
  predicate matrices at construction boundaries.
- Make `.toroidal()` the periodic image-point constructor and move wrapping-only
  construction to `.canonicalized_toroidal()`.
- Align pinned just, rumdl, taplo, dprint, and typos setup through cargo installs
  instead of Homebrew.
- Disable la-stack default features explicitly while selecting exact arithmetic.

BREAKING CHANGE: `.toroidal()` now builds the periodic image-point quotient.
Callers that only want coordinate wrapping must use `.canonicalized_toroidal()`.

BREAKING CHANGE: `.toroidal_periodic()` has been removed.

BREAKING CHANGE: Error types that can carry la-stack diagnostics now implement
PartialEq without Eq because la-stack 0.4.3 diagnostics can contain floating
point payloads.

BREAKING CHANGE: `geometry::matrix::SINGULARITY_TOLERANCE` has been removed;
singular solve tolerances are now owned by the la-stack shim.

Closes #424
@acgetchell acgetchell self-assigned this Jun 9, 2026
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Split toroidal builder modes into explicit .canonicalized_toroidal() (wrap-only) and .toroidal() (image-point periodic), adopt la-stack runtime dispatch and typed LaError mapping at the matrix boundary, remove Eq derives from many error enums, refactor predicate/SoS/circumsphere flows and tests, and bump CI/just tooling pins and setup scripts.

Changes

Builders, Tests, and Docs (Toroidal modes)

Layer / File(s) Summary
Builder API: canonicalized vs periodic
src/delaunay/builder.rs
Adds canonicalized_toroidal() for canonicalization-only wrapping; toroidal() now selects the periodic image-point path; removes toroidal_periodic() and updates builder docs and fields.
Builder tests & helpers updated
tests/triangulation_builder.rs, src/core/algorithms/flips.rs
Tests and helpers renamed/rewired to use canonicalized_toroidal() for wrapping-only checks and toroidal() for periodic-image tests; periodic helper renamed to toroidal_vertices.
User docs updated
README.md, docs/api_design.md, docs/workflows.md, docs/topology.md, docs/invariants.md, docs/limitations.md, docs/ORIENTATION_SPEC.md
Examples, sections, and guidance rewritten to describe .canonicalized_toroidal() vs .toroidal() and remove legacy “Phase” / toroidal_periodic references.

la-stack Boundary, Matrix, and Predicate Changes

Layer / File(s) Summary
la-stack dependency & matrix boundary
Cargo.toml, src/geometry/matrix.rs, tests/prelude_exports.rs
Bumps la-stack to 0.4.3, aliases MAX_STACK_MATRIX_DIM, implements From<LaError> for StackMatrixDispatchError, rewrites dispatch macros to use la_stack::try_with_stack_matrix!, and re-exports LaError via the crate prelude.
Matrix helpers and determinant API
src/geometry/matrix.rs, src/geometry/predicates.rs, src/geometry/sos.rs
Introduces matrix_fast_filter and matrix_direct_det_is_finite, changes matrix_get/matrix_set to checked APIs returning StackMatrixDispatchError, refactors predicate fast-filter gating, and updates SoS/determinant tests to use try_from_rows.
Predicate/SoS test updates
src/geometry/predicates.rs, src/geometry/sos.rs
Stage-1 fast-filter paths unified to matrix_fast_filter; Stage-2 exact-arithmetic gating caches finiteness; NaN/non-finite test coverage now asserts LaError::NonFinite boundary behavior.

Circumsphere, Measures, and Error Plumbing

Layer / File(s) Summary
Circumcenter fallback & linear-algebra error handling
src/geometry/util/circumsphere.rs, src/geometry/util/measures.rs
Switches LU threshold to DEFAULT_SINGULAR_TOL, uses LaVector::try_new, changes LU near-singularity fallback to solve_exact_rounded_f64, and propagates LaError variants into public CircumcenterError/measure helpers.
Coordinate conversion and public conversions
src/geometry/traits/coordinate.rs, src/lib.rs
Import LaError from crate::geometry::matrix, remove #[from] on some LaError fields in public errors in favor of #[source], and add From<LaError> impls mapping matrix-layer errors to public conversion errors; update tests accordingly.

Eq-derive removals & comment cleanup

Layer / File(s) Summary
Remove Eq derives
src/** (multiple files), benches/*
Many public error enums across core, delaunay, geometry, and topology drop Eq while keeping PartialEq.
Comments/docstrings
src/core/*, src/delaunay/construction.rs, docs/*
Replaced “Phase 1/2/3” phrasing with descriptive wording (e.g., “KEY-BASED ACCESS METHODS”).

CI, justfile, and Tooling Docs

Layer / File(s) Summary
CI workflow pin bumps
.github/workflows/ci.yml, .github/workflows/codecov.yml
Bumps JUST_VERSION to 1.52.0, RUMDL_VERSION to 0.2.10, and TYPOS_VERSION to 1.47.2 in CI workflows.
Justfile: Cargo-based pinned tooling
justfile, docs/dev/tooling-alignment.md
Replaces Homebrew install branches with Cargo cargo install --locked installs; adds strict version checks, PATH setup from $CARGO_HOME, and documents pinned tool versions and MSRV guidance.
Tooling docs and README snippets
docs/dev/tooling-alignment.md, README.md
Document new pinned tooling, MSRV (Rust 1.96.0), and short just quickstart instructions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • acgetchell/delaunay#366: Overlaps changes to incremental-insertion/NeighborRebuildError and related insertion error types.
  • acgetchell/delaunay#155: Related la-stack migration and matrix/predicate plumbing changes at the geometry boundary.
  • acgetchell/delaunay#417: Related toroidal/periodic construction pipeline changes and validation guardrails.

🐰 I mapped the torus with care,

canonical wraps here, periodic elsewhere,
LaError whispers from the stack,
Eq dropped lightly from the pack,
Tools pinned, tests march on with flair.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/424-la-stack-api

@codacy-production

codacy-production Bot commented Jun 9, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 7 complexity

Metric Results
Complexity 7

View in Codacy

🟢 Coverage 96.74% diff coverage · +0.45% coverage variation

Metric Results
Coverage variation +0.45% coverage variation (-1.00%)
Diff coverage 96.74% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (2f310d9) 63058 57083 90.52%
Head commit (b1c19fd) 62824 (-234) 57154 (+71) 90.97% (+0.45%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#438) 184 178 96.74%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@coderabbitai coderabbitai Bot added rust Pull requests that update rust code breaking change geometry Geometry-related issues api labels Jun 9, 2026
@codecov

codecov Bot commented Jun 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.34146% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.95%. Comparing base (2f310d9) to head (b1c19fd).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/geometry/util/circumsphere.rs 70.00% 3 Missing ⚠️
src/geometry/matrix.rs 96.61% 2 Missing ⚠️
src/geometry/util/measures.rs 94.44% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #438      +/-   ##
==========================================
+ Coverage   90.51%   90.95%   +0.43%     
==========================================
  Files          71       71              
  Lines       62848    62595     -253     
==========================================
+ Hits        56888    56932      +44     
+ Misses       5960     5663     -297     
Flag Coverage Δ
unittests 90.95% <96.34%> (+0.43%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
README.md (1)

239-257: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clarify that this example is canonicalized, not periodic.

Line 241 says “periodic boundary conditions,” but the snippet uses .canonicalized_toroidal([..]), which does not build periodic quotient neighbor rewiring. Please reword the intro (or switch the snippet to .toroidal([..])) so users choose the correct mode.

✏️ Suggested doc tweak
-For periodic boundary conditions, use `DelaunayTriangulationBuilder`:
+For toroidal wrapping (canonicalized coordinates without periodic quotient rewiring), use `DelaunayTriangulationBuilder`:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 239 - 257, The README currently says "periodic
boundary conditions" but the example uses
DelaunayTriangulationBuilder::canonicalized_toroidal which is not the periodic
(quotient-rewired) mode; either change the explanatory text to clarify this
example demonstrates the canonicalized toroidal mode (mentioning
canonicalized_toroidal specifically) or swap the example call to
DelaunayTriangulationBuilder::toroidal to show true periodic/quotient behavior;
update the surrounding sentence to reference the chosen symbol
(canonicalized_toroidal or toroidal) so readers pick the correct mode.
src/geometry/matrix.rs (1)

208-228: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Avoid NaN fallback in determinant error path.

Line 227 returns f64::NAN for backend errors, which silently discards sign/error semantics and can mask predicate failures. Please surface this as a typed error path instead of collapsing to NaN.

As per coding guidelines, “No f64 operation may silently lose sign information; unwrap_or(NaN), unwrap_or(f64::INFINITY) … are anti-patterns.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/geometry/matrix.rs` around lines 208 - 228, The determinant function
currently swallows backend errors by returning f64::NAN; change it to surface
errors as a typed result instead: update pub fn determinant<const D: usize>(m:
&Matrix<D>) -> Result<f64, LaError> (or add a new fallible variant like
determinant_checked) and propagate m.det()'s Result directly (map Ok(det) and
forward Err(e), handling LaError::Singular by returning Ok(0.0) if you want to
preserve that behavior), update the function docstring and any callers/tests to
handle Result, and remove the NaN fallback branch that returns f64::NAN; keep
references to Matrix, determinant, m.det(), and LaError::Singular when making
the change.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/geometry/util/measures.rs`:
- Around line 271-275: Change gram_determinant_ldlt to return Result<f64,
CircumcenterError> instead of f64; remove the mapping of determinant errors to
f64::NAN and instead propagate the underlying factorization/determinant errors
by converting LaError into CircumcenterError (preserve error context) when
ldlt.det() returns Err. Update the match on ldlt.det() to return Ok(det) on
success and Err(...) with a wrapped CircumcenterError for all failure cases
(including singular), and then update callers of gram_determinant_ldlt to handle
the Result (propagate or map to higher-level errors) rather than expecting NaN
sentinel values.

---

Outside diff comments:
In `@README.md`:
- Around line 239-257: The README currently says "periodic boundary conditions"
but the example uses DelaunayTriangulationBuilder::canonicalized_toroidal which
is not the periodic (quotient-rewired) mode; either change the explanatory text
to clarify this example demonstrates the canonicalized toroidal mode (mentioning
canonicalized_toroidal specifically) or swap the example call to
DelaunayTriangulationBuilder::toroidal to show true periodic/quotient behavior;
update the surrounding sentence to reference the chosen symbol
(canonicalized_toroidal or toroidal) so readers pick the correct mode.

In `@src/geometry/matrix.rs`:
- Around line 208-228: The determinant function currently swallows backend
errors by returning f64::NAN; change it to surface errors as a typed result
instead: update pub fn determinant<const D: usize>(m: &Matrix<D>) -> Result<f64,
LaError> (or add a new fallible variant like determinant_checked) and propagate
m.det()'s Result directly (map Ok(det) and forward Err(e), handling
LaError::Singular by returning Ok(0.0) if you want to preserve that behavior),
update the function docstring and any callers/tests to handle Result, and remove
the NaN fallback branch that returns f64::NAN; keep references to Matrix,
determinant, m.det(), and LaError::Singular when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 98555f1b-5c04-4bd9-95bb-71ace781169f

📥 Commits

Reviewing files that changed from the base of the PR and between 2f310d9 and f612f56.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (47)
  • .github/workflows/ci.yml
  • .github/workflows/codecov.yml
  • Cargo.toml
  • README.md
  • benches/common/flip_workflows.rs
  • docs/ORIENTATION_SPEC.md
  • docs/api_design.md
  • docs/dev/tooling-alignment.md
  • docs/invariants.md
  • docs/limitations.md
  • docs/numerical_robustness_guide.md
  • docs/topology.md
  • docs/workflows.md
  • justfile
  • src/core/algorithms/flips.rs
  • src/core/algorithms/incremental_insertion.rs
  • src/core/algorithms/locate.rs
  • src/core/algorithms/pl_manifold_repair.rs
  • src/core/collections/aliases.rs
  • src/core/collections/helpers.rs
  • src/core/collections/secondary_maps.rs
  • src/core/construction.rs
  • src/core/facet.rs
  • src/core/query.rs
  • src/core/simplex.rs
  • src/core/tds.rs
  • src/core/util/delaunay_validation.rs
  • src/delaunay/builder.rs
  • src/delaunay/construction.rs
  • src/delaunay/delaunayize.rs
  • src/delaunay/validation.rs
  • src/geometry/algorithms/convex_hull.rs
  • src/geometry/matrix.rs
  • src/geometry/predicates.rs
  • src/geometry/quality.rs
  • src/geometry/sos.rs
  • src/geometry/traits/coordinate.rs
  • src/geometry/util/circumsphere.rs
  • src/geometry/util/measures.rs
  • src/lib.rs
  • src/topology/manifold.rs
  • src/topology/traits/global_topology_model.rs
  • src/topology/traits/topological_space.rs
  • tests/circumsphere_debug_tools.rs
  • tests/delaunay_edge_cases.rs
  • tests/regressions.rs
  • tests/triangulation_builder.rs

Comment thread src/geometry/util/measures.rs Outdated
- Encapsulate stack-allocated linear algebra behind the geometry matrix shim so
  the rest of Delaunay avoids depending on la-stack internals.
- Preserve typed la-stack backend failures through determinant and Gram-measure
  paths instead of converting them to NaN sentinels.
- Re-export LaError from the focused geometry prelude for callers of fallible
  matrix helpers.
- Refresh README, roadmap, and code-organization docs around focused preludes,
  feature coverage, topology modes, and current performance limits.

BREAKING CHANGE: geometry::matrix::determinant now returns Result<f64, LaError>
instead of f64, so callers must handle backend determinant errors explicitly.

Closes #424
@acgetchell acgetchell enabled auto-merge (squash) June 9, 2026 18:39

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

402-402: ⚠️ Potential issue | 🟡 Minor

Fix broken README anchor to the toroidal workflow section

docs/workflows.md#builder-api-toroidal-periodic-triangulations doesn’t exist in docs/workflows.md (no matching heading or explicit id/anchor). The toroidal section present is ## Builder API: toroidal construction modes (anchor would be #builder-api-toroidal-construction-modes).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 402, The README link target is pointing to a non-existent
anchor; update the link target for "[toroidal construction workflow]" to the
correct anchor by replacing
docs/workflows.md#builder-api-toroidal-periodic-triangulations with
docs/workflows.md#builder-api-toroidal-construction-modes so it matches the "##
Builder API: toroidal construction modes" heading.

Source: Learnings

🧹 Nitpick comments (1)
src/geometry/matrix.rs (1)

375-394: ⚡ Quick win

Cover determinant across D=2 through D=5.

The new Result<f64, LaError> contract is only exercised on Matrix<2>. Since this boundary is dimension-generic, a regression in the 3×3–5×5 paths would currently slip through. Please add macro-based regular, singular, and non-finite cases for D=2 through D=5.

As per coding guidelines: “Unit tests must cover known values, error paths, and dimension-generic correctness; dimension-generic tests MUST cover D=2 through D=5 whenever feasible using pastey macros”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/geometry/matrix.rs` around lines 375 - 394, Add dimension-generic tests
for determinant across D=2..5 by creating a small macro (using paste or a simple
macro_rules!) that generates three tests per dimension: a regular case asserting
determinant(&Matrix::<D>::try_from_rows(...)) == expected with
assert_relative_eq!, a singular case asserting 0.0, and a non-finite backend
error case asserting Err(LaError::NonFinite { .. }) with assert_matches!;
reference the determinant function, Matrix::<N>::try_from_rows,
LaError::NonFinite, assert_relative_eq!, and assert_matches! in the macro so
each generated test covers D=2 through D=5.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@README.md`:
- Line 402: The README link target is pointing to a non-existent anchor; update
the link target for "[toroidal construction workflow]" to the correct anchor by
replacing docs/workflows.md#builder-api-toroidal-periodic-triangulations with
docs/workflows.md#builder-api-toroidal-construction-modes so it matches the "##
Builder API: toroidal construction modes" heading.

---

Nitpick comments:
In `@src/geometry/matrix.rs`:
- Around line 375-394: Add dimension-generic tests for determinant across D=2..5
by creating a small macro (using paste or a simple macro_rules!) that generates
three tests per dimension: a regular case asserting
determinant(&Matrix::<D>::try_from_rows(...)) == expected with
assert_relative_eq!, a singular case asserting 0.0, and a non-finite backend
error case asserting Err(LaError::NonFinite { .. }) with assert_matches!;
reference the determinant function, Matrix::<N>::try_from_rows,
LaError::NonFinite, assert_relative_eq!, and assert_matches! in the macro so
each generated test covers D=2 through D=5.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 4f2c1583-a905-4fd2-ba04-f7fc5a7bdfba

📥 Commits

Reviewing files that changed from the base of the PR and between f612f56 and b1c19fd.

📒 Files selected for processing (8)
  • README.md
  • docs/code_organization.md
  • docs/roadmap.md
  • src/geometry/matrix.rs
  • src/geometry/util/measures.rs
  • src/lib.rs
  • tests/circumsphere_debug_tools.rs
  • tests/prelude_exports.rs
✅ Files skipped from review due to trivial changes (2)
  • docs/roadmap.md
  • docs/code_organization.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib.rs

@acgetchell acgetchell merged commit 8e58d57 into main Jun 9, 2026
24 checks passed
@acgetchell acgetchell deleted the refactor/424-la-stack-api branch June 9, 2026 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api breaking change geometry Geometry-related issues rust Pull requests that update rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use upstream la-stack runtime matrix dispatch helper

1 participant