Skip to content

perf: switch FastKernel to insphere_lifted and enable LTO#234

Merged
acgetchell merged 4 commits intomainfrom
perf/insphere-lifted-lto
Mar 8, 2026
Merged

perf: switch FastKernel to insphere_lifted and enable LTO#234
acgetchell merged 4 commits intomainfrom
perf/insphere-lifted-lto

Conversation

@acgetchell
Copy link
Owner

Switch FastKernel::in_sphere() to use insphere_lifted() for 5.3x speedup in 3D. Add release profile optimization with thin LTO and codegen-units=1.

Benchmarks across dimensions (2D-5D):

  • insphere_lifted is 5.3x faster in 3D (15.5 ns vs 81.7 ns)
  • Random query test: 3.75x faster (20.0 µs vs 75.0 µs for 1000 queries)
  • insphere_lifted consistently fastest across all dimensions

Performance gains attributed to la-stack v0.2.0's closed-form determinants for D=1-4.

Changes:

  • Cargo.toml: Add [profile.release] with lto="thin" and codegen-units=1
  • src/geometry/kernel.rs: Switch FastKernel to use insphere_lifted()

Expected impact: 5-6x improvement in incremental insertion hot path.

All tests pass (1279 unit tests, 505 doctests, full CI green).

Resolves: #206

Switch FastKernel::in_sphere() to use insphere_lifted() for 5.3x speedup in 3D.
Add release profile optimization with thin LTO and codegen-units=1.

Benchmarks across dimensions (2D-5D):
- insphere_lifted is 5.3x faster in 3D (15.5 ns vs 81.7 ns)
- Random query test: 3.75x faster (20.0 µs vs 75.0 µs for 1000 queries)
- insphere_lifted consistently fastest across all dimensions

Performance gains attributed to la-stack v0.2.0's closed-form determinants for D=1-4.

Changes:
- Cargo.toml: Add [profile.release] with lto="thin" and codegen-units=1
- src/geometry/kernel.rs: Switch FastKernel to use insphere_lifted()

Expected impact: 5-6x improvement in incremental insertion hot path.

All tests pass (1279 unit tests, 505 doctests, full CI green).

Resolves: #206

Co-Authored-By: Oz <oz-agent@warp.dev>
@coderabbitai
Copy link

coderabbitai bot commented Mar 8, 2026

Walkthrough

Switches FastKernel to call insphere_lifted, updates predicate determinant/ parity handling and docs/tests (2D–5D), and adds release profile LTO/codegen settings plus a new benchmark target.

Changes

Cohort / File(s) Summary
Build Configuration
Cargo.toml
Adds [profile.release] with lto = "thin" and codegen-units = 1; adds [[bench]] entry circumsphere_containment -> benches/circumsphere_containment.rs.
Geometry Kernel
src/geometry/kernel.rs
FastKernel in_sphere now calls insphere_lifted; error mapping preserved and updated to propagate CoordinateConversionError or map to a ConversionFailed variant; import updated; two new error-path tests added.
Predicates & Tests
src/geometry/predicates.rs
Expanded docs and performance notes; determinant normalization and sign interpretation adjusted to account for dimension parity; extensive parity-focused unit tests added (2D–5D) validating insphere, insphere_distance, and insphere_lifted behavior and edge cases.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Poem

🐰
I hopped through matrices, tiny and grand,
Lifted a sphere with a careful hand,
Thin LTO hums, benches set to run,
Parity nodded — the determinants done,
I nibble code and dream of sun.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main changes: switching FastKernel to use insphere_lifted and enabling LTO in the release profile.
Description check ✅ Passed The description clearly relates to the changeset, providing specific performance metrics, changes made, and test results that directly correspond to the code modifications.
Linked Issues check ✅ Passed The PR addresses objectives 1, 2, and 4 from issue #206. It switches to insphere_lifted (a faster variant than insphere_distance mentioned in #206), enables LTO and codegen-units=1, and includes comprehensive predicate documentation and testing improvements.
Out of Scope Changes check ✅ Passed All changes align with the linked issue #206 objectives: profile optimization (item 4), predicate variant switching (item 1), and enhanced test coverage. The expanded documentation and parity tests support the performance and correctness goals.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch perf/insphere-lifted-lto

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai bot added rust Pull requests that update rust code geometry Geometry-related issues labels Mar 8, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/geometry/kernel.rs`:
- Around line 250-257: The current map_err on insphere_lifted in
Kernel::in_sphere stringifies every error into
CoordinateConversionError::ConversionFailed, losing original
CellValidationError::CoordinateConversion metadata; change the error mapping to
match the insphere_lifted error and if it is
CellValidationError::CoordinateConversion { source, .. } forward that source
unchanged (propagate the original conversion error), otherwise synthesize
CoordinateConversionError::ConversionFailed (preserving
coordinate_index/coordinate_value/from_type/to_type as before) so only
non-conversion variants are wrapped.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: e2cd9915-4225-4a8e-a606-6829db2a5a9d

📥 Commits

Reviewing files that changed from the base of the PR and between 14ff1b3 and d654e30.

📒 Files selected for processing (2)
  • Cargo.toml
  • src/geometry/kernel.rs

@acgetchell acgetchell self-assigned this Mar 8, 2026
Update insphere predicate documentation with comprehensive benchmark results
and improve error propagation in FastKernel::in_sphere.

Documentation updates:
- Add performance sections to insphere(), insphere_distance(), and insphere_lifted()
- Document benchmark results showing insphere_lifted is 5.3x faster in 3D
- Mark insphere_lifted as the recommended high-performance implementation
- Explain performance gains from relative coordinates and la-stack v0.2.0's
  closed-form determinants for D=1-4

Error handling improvement:
- Fix FastKernel::in_sphere to preserve CoordinateConversionError metadata
- When insphere_lifted returns CellValidationError::CoordinateConversion,
  forward the original source error instead of stringifying it
- Only wrap non-conversion errors in new CoordinateConversionError
@coderabbitai coderabbitai bot added the documentation Improvements or additions to documentation label Mar 8, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

669-683: Add a regression that exercises this parity branch under both simplex orientations.

This is the behavioral change in the PR, but the current insphere tests still cover only one orientation per dimension, and the 2D comprehensive test still leaves std vs lifted disabled. A bad parity_sign * orient_sign combination for reversed vertex order would still slip through here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/geometry/predicates.rs` around lines 669 - 683, Add tests that exercise
the parity branch for both Orientation::POSITIVE and Orientation::NEGATIVE so
the parity_sign * orient_sign combination is validated; specifically add
insphere/regression cases that call the code path computing dimension_is_even,
parity_sign, orient_sign and det_norm for even and odd D with both vertex
orderings. Update the existing 2D comprehensive test to enable the "std vs
lifted" comparison (it is currently disabled) and ensure each test asserts
identical results between the lifted formulation and the standard predicate for
both orientations. Ensure test names reference the predicate (insphere) and
orientation so failures point to the parity branch.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/geometry/predicates.rs`:
- Around line 185-193: The docs recommending insphere_lifted should include a
robustness caveat: update the docblocks that currently endorse insphere_lifted
(the Performance/recommendation paragraphs in predicates.rs that compare
insphere, insphere_distance and insphere_lifted) to add a short sentence noting
that insphere_lifted is a fast floating-point predicate and may be less robust
than robust_insphere, and that callers requiring numerical robustness should use
robust_insphere or RobustKernel (follow the same wording/pattern used in the
kernel.rs FastKernel caveat for 3D+ triangulation); make this change in each
recommendation block where insphere_lifted is promoted so users are warned about
correctness vs performance tradeoffs.

---

Nitpick comments:
In `@src/geometry/predicates.rs`:
- Around line 669-683: Add tests that exercise the parity branch for both
Orientation::POSITIVE and Orientation::NEGATIVE so the parity_sign * orient_sign
combination is validated; specifically add insphere/regression cases that call
the code path computing dimension_is_even, parity_sign, orient_sign and det_norm
for even and odd D with both vertex orderings. Update the existing 2D
comprehensive test to enable the "std vs lifted" comparison (it is currently
disabled) and ensure each test asserts identical results between the lifted
formulation and the standard predicate for both orientations. Ensure test names
reference the predicate (insphere) and orientation so failures point to the
parity branch.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 0af3d387-32e8-4194-ba28-d38426944c31

📥 Commits

Reviewing files that changed from the base of the PR and between d654e30 and 0e4739c.

📒 Files selected for processing (2)
  • src/geometry/kernel.rs
  • src/geometry/predicates.rs

Add robustness warnings to insphere_lifted documentation noting it's a
fast floating-point predicate that may be less robust than robust_insphere
for nearly-degenerate configurations. Direct users to RobustKernel for 3D+
triangulations requiring numerical robustness.

Documentation updates:
- Add robustness caveat to insphere_distance() recommendation (lines 192-196)
- Add robustness caveat to insphere() performance section (lines 297-302)
- Add new "Robustness" section to insphere_lifted() docs (lines 500-505)
- All warnings reference RobustKernel and follow FastKernel warning pattern

Testing improvements:
- Add test_insphere_lifted_parity_branch_positive_orientation
  Tests parity_sign * orient_sign path for 2D, 3D, 4D, 5D with POSITIVE orientation
- Add test_insphere_lifted_parity_branch_negative_orientation
  Tests parity_sign * orient_sign path for 2D, 3D, 4D, 5D with NEGATIVE orientation
- Each test validates orientation and asserts insphere_lifted matches insphere
- Ensures correctness for even dimensions (2D, 4D) and odd dimensions (3D, 5D)

All 20 predicate tests pass. Documentation builds without warnings.

Addresses inline code review comments for issue #206.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/geometry/predicates.rs (2)

1614-1720: Consider table-driving the parity fixtures.

The two tests repeat nearly identical setup for 2D–5D and both orientations. A small helper over (simplex, expected_orientation, point) would make this regression much easier to extend and less error-prone.

Also applies to: 1723-1828

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/geometry/predicates.rs` around lines 1614 - 1720, The test
test_insphere_lifted_parity_branch_positive_orientation duplicates nearly
identical setups across dimensions and orientations; refactor by creating a
small table-driven helper (e.g., a function like run_insphere_parity_test or a
struct fixture holding (simplex, expected_orientation, test_point)) that
iterates over rows for 2D–5D and both Orientation::POSITIVE/NEGATIVE, and inside
each iteration call simplex_orientation, insphere_lifted and insphere and assert
equality and expected InSphere; replace the repeated blocks in
test_insphere_lifted_parity_branch_positive_orientation (and the similar test at
1723-1828) with calls into this helper to reduce duplication and make it easier
to extend.

1614-1720: Add one FastKernel::in_sphere() regression alongside these parity tests.

These assertions prove the predicate-level parity behavior, but the PR’s actual hot-path change is the enum-to-i32 mapping in src/geometry/kernel.rs:244-267. One positive/negative-orientation regression there would protect the production path from a future sign-mapping slip.

Also applies to: 1723-1828

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/geometry/predicates.rs`:
- Around line 1614-1720: The test
test_insphere_lifted_parity_branch_positive_orientation duplicates nearly
identical setups across dimensions and orientations; refactor by creating a
small table-driven helper (e.g., a function like run_insphere_parity_test or a
struct fixture holding (simplex, expected_orientation, test_point)) that
iterates over rows for 2D–5D and both Orientation::POSITIVE/NEGATIVE, and inside
each iteration call simplex_orientation, insphere_lifted and insphere and assert
equality and expected InSphere; replace the repeated blocks in
test_insphere_lifted_parity_branch_positive_orientation (and the similar test at
1723-1828) with calls into this helper to reduce duplication and make it easier
to extend.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: aa83b403-b8e4-4da3-810a-2b03ee3db0bc

📥 Commits

Reviewing files that changed from the base of the PR and between 0e4739c and cb5bd46.

📒 Files selected for processing (1)
  • src/geometry/predicates.rs

@codacy-production
Copy link

codacy-production bot commented Mar 8, 2026

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
+0.03% (target: -1.00%) 50.00%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (14ff1b3) 13245 8188 61.82%
Head commit (e38fb83) 13252 (+7) 8196 (+8) 61.85% (+0.03%)

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 (#234) 8 4 50.00%

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%

See your quality gate settings    Change summary preferences

@codecov
Copy link

codecov bot commented Mar 8, 2026

Codecov Report

❌ Patch coverage is 50.00000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.87%. Comparing base (14ff1b3) to head (e38fb83).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/geometry/kernel.rs 50.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #234      +/-   ##
==========================================
+ Coverage   61.85%   61.87%   +0.02%     
==========================================
  Files          49       49              
  Lines       13238    13245       +7     
==========================================
+ Hits         8188     8196       +8     
+ Misses       5050     5049       -1     
Flag Coverage Δ
unittests 61.87% <50.00%> (+0.02%) ⬆️

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

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

Introduce a `check_insphere_parity` helper function to deduplicate test
logic for parity sign checks across 2D-5D. Add coverage for the
`InsufficientVertices` and `DegenerateSimplex` error paths in the
`FastKernel::in_sphere` implementation. This is an internal change.

Refs: #206
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/geometry/predicates.rs`:
- Around line 187-193: The current doc comment overstates performance by saying
insphere_lifted is “significantly faster across all dimensions”; change the
phrasing to soften the claim—e.g., say insphere_lifted is the “fastest overall”
or “preferred default for performance” and explicitly note that in 2D
insphere_lifted is roughly on par with insphere (and insphere_distance is slower
in 2D). Update the three affected doc comment blocks that mention
insphere_lifted/insphere/insphere_distance (the block around the diff shown and
the other occurrences at the ranges you noted) to use the softened wording and
the explicit 2D parity note, keeping the benchmark bullets intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: ffbe0e4a-7174-4a10-b38b-4bdf7fd171b9

📥 Commits

Reviewing files that changed from the base of the PR and between cb5bd46 and e38fb83.

📒 Files selected for processing (2)
  • src/geometry/kernel.rs
  • src/geometry/predicates.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/geometry/kernel.rs

Comment on lines +187 to +193
/// Benchmarks show that [`insphere_lifted`] is significantly faster across all dimensions:
/// - **3D**: 5.3x faster than [`insphere`], 2.5x faster than `insphere_distance`
/// - **4D-5D**: 1.6-2.9x faster than [`insphere`], comparable to `insphere_distance`
/// - **2D**: `insphere_distance` is 2x slower than [`insphere`] or [`insphere_lifted`]
///
/// **Recommendation**: Use [`insphere_lifted`] for optimal performance in production code.
/// Note that `insphere_lifted` is a fast floating-point predicate that may be less robust
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Soften the “across all dimensions” performance claim.

The bullets here already say 2D is roughly on par with insphere, so phrases like “significantly faster across all dimensions” / “superior performance across all dimensions” overstate the measurements. I’d reword this as “fastest overall” or “preferred default,” with an explicit note that 2D is near parity.

Also applies to: 293-298, 494-506

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/geometry/predicates.rs` around lines 187 - 193, The current doc comment
overstates performance by saying insphere_lifted is “significantly faster across
all dimensions”; change the phrasing to soften the claim—e.g., say
insphere_lifted is the “fastest overall” or “preferred default for performance”
and explicitly note that in 2D insphere_lifted is roughly on par with insphere
(and insphere_distance is slower in 2D). Update the three affected doc comment
blocks that mention insphere_lifted/insphere/insphere_distance (the block around
the diff shown and the other occurrences at the ranges you noted) to use the
softened wording and the explicit 2D parity note, keeping the benchmark bullets
intact.

@acgetchell acgetchell merged commit 91e290f into main Mar 8, 2026
9 checks passed
@acgetchell acgetchell deleted the perf/insphere-lifted-lto branch March 8, 2026 02:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation geometry Geometry-related issues rust Pull requests that update rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf: predicate and build optimizations

1 participant