Skip to content

hpc::phase: phases in turns, a (cos, sin) LUT with stated error bounds, a drift-free accumulator - #343

Merged
AdaWorldAPI merged 1 commit into
masterfrom
ccr-b2e415d9-4jfvyk-phase-lut
Oct 8, 2026
Merged

AdaWorldAPI merged 1 commit into
masterfrom
ccr-b2e415d9-4jfvyk-phase-lut

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

This PR adds src/hpc/phase.rs, re-exported from ndarray::simd. It is the "ADOPT" item of the lance-graph phasor probe (D-PHT-1, lance-graph #1416).

What

Phases. A phase is a u32 in turns, with 2^32 = one rotation. So 3θ is p.wrapping_mul(3), θ + φ is p.wrapping_add(q), and wraparound is free.

item role
turns_from_radians / radians_from_turns Conversion. Rounds to the nearest phase; negative angles wrap; NaN maps to 0.
PhaseLut 2^bits [cos, sin] pairs, bits in 2..=20.
phase_lut_4096() A shared 32 KB table, built on first use.
PhaseStep { start, step } at(n) = start + n·step modulo one turn, in closed form, so it cannot drift. from_radians reports how far the representable step is from the requested one.

PhaseLut methods:

  • nearest(p) and lerp(p) (linear interpolation), plus lerp_batch.
  • Per-component error bounds, so a caller can carry them into an exact decision:
    • nearest_error_bound() is π/2^bits plus f32 rounding;
    • lerp_error_bound() is h²/8 (chord sag, with h = 2π/2^bits) plus 4·f32 epsilon.

Why

ndarray had no phase LUT, no CORDIC and no SIMD sin/cos. vml::vscos/vssin call scalar cos/sin per lane.

The lance-graph probe measured interpolation at 2^12 entries:

  • Accuracy: the same as f32 sin_cos (4.6e-7 vs 5.1e-7 relative).
  • Speed: about 4.5× faster than f32 sin_cos and 12× faster than f64 (x86-64-v3, release, 1M random phases).
  • Drift: an integer accumulator has none; an f32 complex recurrence reached 1.95 units on R = 100 after 1M steps.

The lookups here are scalar. No SIMD path is claimed. A gather batch is a separate, unmeasured step.

Tests

  • Bounds, checked two-sided:
    • lookups never exceed their bound, for 4, 8, 10, 12 and 16 bits;
    • the bounds are not vacuous: nearest reaches more than half of its bound, and lerp more than a tenth at ≤ 12 bits;
    • interpolation beats the nearest entry.
  • Wrap and multiply: the last interval interpolates into entry 0, and wrapping_mul(3) equals 3θ mod 2π.
  • Conversions: they round-trip, negative angles wrap, NaN maps to 0, and from_radians reports the step it actually took.
  • Accumulator: after 1M steps the phase equals the closed form, and the looked-up point stays within the bound.
  • Batch and input checks: the batch equals the scalar lookup; mismatched lengths and out-of-range sizes panic.
  • Doctests: 20, one per public item.

Disable runs, each red then restored:

  • nearest without the half-step rounding;
  • lerp without the wrap into entry 0;
  • the lerp bound without the chord sag;
  • at ignoring start.

Gates:

  • cargo test -p ndarray --lib: 2543 passed.
  • cargo clippy -p ndarray --lib --tests -- -D warnings: clean.
  • fmt: clean.
  • Every compile used debug 0. Only the native realization was run; the module has no target-specific code.

The blackboard entry is prepended.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EFw2WdKr1oxvaKCJC2ua2R


Generated by Claude Code

…s, a drift-free accumulator

A phase is a u32 in turns (2^32 = one rotation), so 3θ is
p.wrapping_mul(3) and wraparound is free. PhaseLut maps a phase to
(cos, sin) through a 2^bits table, at the nearest entry or by linear
interpolation, and states a per-component error bound for each, so a
caller can carry it into an exact decision. PhaseStep gives the phase
after n steps in closed form, so it cannot drift. Re-exported from
ndarray::simd.

Measured in the lance-graph phasor probe (#1416): interpolation at 2^12
entries matches f32 sin_cos accuracy at about 4.5x its speed and 12x
f64. The lookups are scalar; no SIMD path is claimed.

Tests check each bound two-sided (never exceeded, not vacuous). Four
disable runs are red.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EFw2WdKr1oxvaKCJC2ua2R
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 179d6b0c-b3e3-40d1-b36d-de90243da307
📥 Commits

Reviewing files that changed from the base of the PR and between 30ce119 and b5454d1.

📒 Files selected for processing (4)
  • .claude/blackboard.md
  • src/hpc/mod.rs
  • src/hpc/phase.rs
  • src/simd.rs
 _______________________________
< Yippee-ki-yay, mother-bugger! >
 -------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.


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

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review October 8, 2026 19:39
@AdaWorldAPI
AdaWorldAPI merged commit 36ce111 into master Oct 8, 2026
25 checks passed
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-08T19:41:23.691481Z b5454d1 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

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.

2 participants