Skip to content

Adopt tap::dsp::packed_spectrum per header (77 sites) #51

Description

@tap

What

DspTap tap/DspTap#19 (FFT plan Stage 5) adds include/tap/dsp/fft/spectrum.h: tap::dsp::packed_spectrum<Sample>, a non-owning, constexpr, allocation-free view over the packed real spectrum that basic_real_fft produces and consumes. Its docstring is now the one home of the packing (bin[k] = a[2k] + i·a[2k+1], DC at a[0], Nyquist at a[1], W = exp(+2πi/N), inverse unnormalized), with native accessors dc(), nyquist(), re(k), im(k), power(k), num_bins(), and one convention-flipping accessor, bin_engineering(k), which conjugates.

MuTap re-derives that packing by hand at 77 sites. Per the plan's adversarial review (P2), the DspTap PR migrates DspTap's own consumers only; MuTap adopts the view per header, when each header is next touched, never as one wholesale rewrite.

The sites

header hand-indexed spectrum sites
fdaf.h 25
fd_kalman.h 28
nn_suppressor.h 15
postfilter.h 9

The gate, per header

Each adopting PR is gated by both of:

  1. Fingerprint identical. MuTap's fingerprint harness (Stage 1) must hash byte-identically before and after, on the same host, compiler and flags, for every chain the header participates in. The view inlines to the same index expressions, so any difference is a migration error, not rounding.
  2. 0% icount. The ratcheted instruction counts for the scenarios that exercise the header must not move (an accepted regression is a written commit, per D11).

The rule for the hot loops

The ratcheted loops in these headers compute native-convention complex products by hand (spectral products between spectra from this library need no conjugation). They adopt the native accessors only: re(k), im(k), dc(), nyquist(), power(k). They must never use bin_engineering(): it conjugates, it constructs a std::complex temporary, and it exists for textbook phase math (pvoc), not for regressor accumulation. A hot loop that grows a sign flip under this migration has been migrated wrong, and the fingerprint gate above is what catches it.

num_bins() replaces every hand-computed N/2 + 1 at the same time.

Order

Wait for the DspTap PR to merge and the submodule pin to move (rollout rule: DspTap squash → MuTap pin + code → MuTap-Max pin). Then one PR per header, in whatever order the headers are next touched for other reasons.

References: tap/DspTap#19; DspTap docs/audit-fft-and-code-smells.md, Part 1 F8, Part 3 Stage 5, Part 6 P2, Part 13.

🤖 Generated with Claude Code

https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions