Skip to content

feat: add stable unsigned vector angles - #274

Merged
acgetchell merged 3 commits into
mainfrom
feat/249-vector-angles
Oct 8, 2026
Merged

acgetchell merged 3 commits into
mainfrom
feat/249-vector-angles

Conversation

@acgetchell

@acgetchell acgetchell commented Oct 8, 2026 •

Copy link
Copy Markdown
Owner

Implements the API and validation work for #249 against the completed Rust 1.99 / LLVM 23 baseline from #251.

angle_between(&[f64], &[f64]) and Vector::angle(&self, &other) compute allocation-free unsigned angles in radians for arbitrary finite nonzero vectors. Shape, empty/zero input, and non-finite coordinate errors retain typed operand and index context. Both entry points share the numerical kernel; fixed-size vectors reuse their finite-storage invariant.

The kernel uses power-of-two scaling, compensated exterior minors, a compensated dot reduction, and atan2. For positive dot products and exterior/dot ratios at most 2^-27, it returns the ratio directly, with the arctangent approximation error bounded below half an ulp. This avoids the subnormal atan2 failures observed by Windows CI. This preserves the least positive subnormal angle and nearly proportional directions whose normalized coordinates would become identical. It accepts overflowing input norms and arbitrary ambient lengths. The documented tradeoff is quadratic work with constant storage; results are rounded, without a certified error bound or correct-rounding claim.

Independent analytical, integer planar cross/dot, and integer Gram-determinant tests cover lengths 0, 1, 2–6, 8, and 64; identical, parallel, antipodal, nearly parallel/antipodal, mixed-scale, subnormal, signed-zero, invalid, rescaling, and allocation cases are included. A 3–6 dimensional Criterion suite compares a valid stable Kahan control, prepared vectors, borrowed slices, and construction-inclusive calls. All 80 measurements, confidence intervals, and source provenance are retained in docs/archive/performance/studies/vector-angles.md and its sidecars.

Validation used just check during iteration. just markdown-fix, just markdown-ci, and final just ci passed. Final CI ran 963 Rust tests and 502 Python tests, default/exact doctests, all-target Clippy, static/configuration checks, benchmark compilation, and examples. Focused numerical and benchmark-input tests passed before timing. Benchmarks used Rust 1.99.0 / LLVM 23.1.1 on an Apple M4 Max, with 50 samples, 1-second warmup, and 2-second measurement targets.

A coverage audit of run 37801925568, generated from 09020aa18a2b233831a8975b343095d2de1670eb, found 96.875% patch coverage against the configured 90% target (2% tolerance). Added tests cover formatter write-failure propagation and the small-angle/normal-subnormal transitions. Local just coverage-ci passed all 876 tests and estimates 97.92% patch line coverage; only the three defensive non-finite-result lines remain uncovered. No coverage exclusions or thresholds were changed. The XML does not collect branch coverage. Final just ci passed in an isolated checkout with the PR's committed dependencies, avoiding concurrent dependency edits in the main checkout.

Agent guidance now permits Git mutations with explicit user approval, limited to the approved operations and task.

Package versions remain 0.4.6. Publishing v0.4.7 and downstream Delaunay adoption are separate maintainer steps; this draft does not perform either.

Summary by CodeRabbit

  • New Features
    • Added unsigned angle calculations for coordinate slices and vectors, returning radians from 0 to π.
    • Added clear errors for mismatched dimensions, empty or zero vectors, and non-finite coordinates.
  • Documentation
    • Documented angle inputs, results, errors, and numerical limitations, including the absence of a certified error bound.
    • Added a performance study comparing angle calculation approaches.
  • Benchmarks
    • Added angle benchmarks for dimensions 3–6 across varied numerical inputs.

- Add allocation-free borrowed-slice and fixed-vector angle APIs with typed
  shape, zero-vector, and non-finite operand errors.
- Preserve extreme scales and tiny separations with power-of-two scaling,
  compensated exterior products, and full-angle atan2 evaluation.
- Add independent numerical regressions and properties, allocation checks,
  stable benchmark comparisons, and retained measurement provenance.
- Document rounded semantics and the quadratic-time, constant-space tradeoff.
- Permit Git mutations in agent guidance when explicitly approved by the user.
- Validate with full just ci: 955 Rust tests, 502 Python tests, default/exact
  doctests, lint checks, benchmark compilation, and examples.

Refs #249
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: acgetchell/la-stack/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 3dd1d1aa-1677-472d-9826-df299e6b926f
📥 Commits

Reviewing files that changed from the base of the PR and between 7ee4bde and 9b18f05.

⛔ Files ignored due to path filters (3)
  • Cargo.lock is excluded by !**/*.lock
  • docs/archive/performance/studies/vector-angles.csv is excluded by !**/*.csv
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (16)
  • README.md
  • REFERENCES.md
  • benches/angle.rs
  • benches/common/angle.rs
  • docs/BENCHMARKING.md
  • docs/archive/performance/studies/vector-angles.md
  • docs/archive/performance/studies/vector-angles.provenance.json
  • docs/code_organization.md
  • docs/mathematical_basis.md
  • pyproject.toml
  • src/angle.rs
  • src/error.rs
  • src/lib.rs
  • src/vector.rs
  • tests/proptest_vector_angles.rs
  • tests/vector_angles.rs
🚧 Files skipped from review as they are similar to previous changes (6)
  • docs/BENCHMARKING.md
  • REFERENCES.md
  • pyproject.toml
  • docs/archive/performance/studies/vector-angles.provenance.json
  • docs/code_organization.md
  • docs/archive/performance/studies/vector-angles.md

Included review availability: This review used your included allowance. 0 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour.


📝 Walkthrough

Walkthrough

The change adds unsigned-angle calculation for borrowed slices and fixed-size vectors, with typed validation errors and a scaled numerical kernel. It adds correctness tests, benchmark fixtures and comparisons, performance-study records, and API documentation. Repository guidance for version-control operations also changes.

Changes

Unsigned vector angles

Layer / File(s) Summary
Angle API and numerical kernel
src/angle.rs, src/error.rs, src/lib.rs, src/vector.rs
Adds the VectorAngle trait and Vector::angle. The implementation validates inputs, scales vector directions by powers of two, uses compensated dot and exterior-product calculations, and uses a small-angle division path or atan2.
Angle correctness and error validation
tests/vector_angles.rs, tests/proptest_vector_angles.rs
Adds analytical and property tests for accuracy, symmetry, scaling, extreme values, input errors, error displays, and allocation behavior.
Benchmark fixtures and measurements
Cargo.toml, benches/angle.rs, benches/common/angle.rs, tests/angle_bench_inputs.rs, docs/BENCHMARKING.md, docs/archive/performance/studies/*
Adds a Criterion suite with four evaluation paths and validated fixtures in dimensions 3–6. Documents benchmark methods, results, provenance, and measurement limits.
Angle API and benchmark documentation
README.md, REFERENCES.md, docs/mathematical_basis.md, docs/code_organization.md, pyproject.toml
Documents the API, mathematical contract, and numerical limits. Updates module, test, benchmark, and study inventories, and changes the configured nextest version and README release-rule match count.

Version-control guidance

Layer / File(s) Summary
Approval and manual-operation guidance
AGENTS.md, docs/dev/MANAGING_CHANGES.md
Allows version-control state changes with explicit approval. Without approval, the guidance says to provide commands for the maintainer to run and to preserve unrelated changes.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant VectorAngle
  participant Vector
  participant angle_kernel
  Caller->>VectorAngle: pass borrowed coordinate slices
  VectorAngle->>angle_kernel: validate and calculate angle
  Caller->>Vector: pass fixed-size vectors
  Vector->>angle_kernel: calculate angle from finite vectors
  angle_kernel-->>Caller: return angle or error
Loading

Merge Risk: ⚪ Minimal · up to 9b18f

No identified issue blocks the unsigned-angle change from merging after normal checks.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: adding stable unsigned vector angle APIs.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@codecov

codecov Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.05195% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 98.12%. Comparing base (b121ea3) to head (9b18f05).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/angle.rs 97.05% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #274      +/-   ##
==========================================
- Coverage   98.13%   98.12%   -0.01%     
==========================================
  Files          13       14       +1     
  Lines        6966     7112     +146     
==========================================
+ Hits         6836     6979     +143     
- Misses        130      133       +3     
Flag Coverage Δ
unittests 98.12% <98.05%> (-0.01%) ⬇️

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[bot]
coderabbitai Bot previously approved these changes Oct 8, 2026
- Use the direct exterior/dot ratio for sufficiently small positive angles,
  with a documented arctangent approximation bound, avoiding platform atan2
  underflow observed by the Windows CI regression tests.
- Test the small-angle transition and normal/subnormal boundary across
  dimensions 2 through 6, 8, and 64 without relaxing existing tiny-angle tests.
- Verify that exact-conversion error formatting propagates writer failures.
- Retain the defensive non-finite-result guard without artificial coverage
  tests, exclusions, or coverage-threshold changes.
- Refresh all 80 benchmark records and retain the original measurements by
  commit for a documented before/after comparison.
- Validate with just check, just coverage-ci (876 tests), and isolated just ci
  (963 Rust tests, 502 Python tests, doctests, lints, benchmarks, and examples).

Refs #249
coderabbitai[bot]
coderabbitai Bot previously approved these changes Oct 8, 2026
- Replace the unreleased angle_between function with VectorAngle::angle on
  coordinate slices, retaining Vector::angle and root/prelude exports.
- Require validated Vector inputs at the internal finite-angle boundary.
- Expand independent rational-reference and typed error-path coverage.
- Replace the angle benchmark study with fresh measurements and provenance
  for the extension API, and update API documentation and examples.
- Refresh locked Rust/Python dependencies and the cargo-nextest tool pin.

Refs #249
@acgetchell
acgetchell marked this pull request as ready for review October 8, 2026 19:53
@acgetchell
acgetchell enabled auto-merge October 8, 2026 19:53
@acgetchell
acgetchell merged commit b8ffb20 into main Oct 8, 2026
22 checks passed
@acgetchell
acgetchell deleted the feat/249-vector-angles branch October 8, 2026 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant