Skip to content

docs: FFT audit and staged plan (revision 3.1) - #25

Merged
tap merged 9 commits into
mainfrom
claude/fft-code-smells-audit-xk4a2g
Sep 17, 2026
Merged

tap merged 9 commits into
mainfrom
claude/fft-code-smells-audit-xk4a2g

Conversation

@tap

@tap tap commented Sep 17, 2026

Copy link
Copy Markdown
Owner

What this changes

Adds docs/audit-fft-and-code-smells.md: the audit of the FFT layer and its relatives across the repo, and the staged plan (revision 3.1) whose end state is one real-FFT contract over double, float, Q15 and Q31, with the #define double float build, the global Ooura symbols and the compiled static library gone. Documentation only; no code changes.

Why

The trigger was the #define double float retargeting of fftsg.c. The audit records what else belongs to the same family (preprocessor-selected backends with layout-by-define, lazy table initialisation on the RT path, packing arithmetic re-derived at every consumer, a 32-bit sample counter that overflows after ~12 h, a substrate with no double profile, and more), ranks it, and sequences the work so each stage is independently landable with a named gate. Two adversarial reviews of the plan (Part 6) and eighteen hostile reviews of the wave-1 PRs (Part 13) are folded in; revision 3.1 is the plan of record that the wave-1 PRs (#17, #18, #19, #20, #21, #22, #23, #24 and tap/MuTap#50) cite. docs/fft-design.md (#18) links this file, so it needs to be on main.

Verification

Prose only. The hosted build and test suite at the base commit 5ca3b1c were run at the start of the audit: warning-free with -DTAP_DSP_WERROR=ON, 160/160 tests. Every source-level claim in Parts 1, 2 and 6 was verified against the file and line it cites at 5ca3b1c; measured numbers in Parts 4, 6 and 7 came from reviewer probes and are labelled as such, with the stage at which a committed test pins them.

Notes for the reviewer

🤖 Generated with Claude Code

https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy


Generated by Claude Code

tap and others added 8 commits September 17, 2026 15:58
…ed plan

Records the findings behind the #define-double-float complaint (symbol
leakage, preprocessor-selected backends with layout-by-define, lazy table
init on the RT path, per-call allocation in the float-I/O overloads,
packing arithmetic re-derived at every consumer) and the relatives found
elsewhere in the repo (32-bit long sample counters, sample_traits with no
double profile, fir_kernels' macro + is_same pattern, noexcept allocation
in solve_dense, pvoc's double float-profile). Lays out a six-stage plan
ending in one Ooura port over double/float/fixed types, and the design
decisions to settle before the port.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy
… plan

Adds Part 4 (scope of the rdft-reachable subset, class shape, tables
built in double at construction, const transforms, the two-pass port
under one bit-exact gate, header-only with an explicit-instantiation
escape hatch, and the cleanup the port enables) and Part 5 (why the
engine should be named for what it is, split_radix_rdft, with Ooura kept
in attribution, NOTICE and the parity test). Records the float-twiddle
defect the #define double float build carries. Adds decisions D7, D8.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy
Two independent hostile reviews (numerics/port and process/ecosystem)
plus an author pass, every accepted item verified against source or a
probe. Blockers resolved: float numerics no longer change inside the
port (the port reproduces the C's table semantics for both precisions,
so float stays bit-identical and no downstream float pin moves); the
'more accurate twiddles' claim was measured and dropped; fp-contraction
becomes a written contract point with a -ffp-contract=off parity gate;
unrunnable M55 gates removed and replaced by compile-only plus MuTap's
QEMU legs; the MuTap CI flag typo that silenced the Ooura-on-M55 leg
becomes a prerequisite; the packed-spectrum view is native-convention
and DspTap-only; licensing text corrected to what Ooura's notice
actually grants; the fixed-point design that failed arithmetic (int32
overflow in the twiddle multiply, runtime twiddle sums up to 2.0 in
cftf1st, inverse structural gain N/2, ~25 dB per-bin SNR at -40 dBFS)
moves to an appendix with its constraints as entry conditions. The
port is split into add / flip / remove PRs, the counter bug ships
alone first, D4 gains an ABI tag, the extern-template hatch is dropped
(verified ineffective for in-class definitions), and F2/F4 in the
audit are reworded to their actual exposure.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy
…test/CI plans

Fixed point returns as Stage 3 (fixed-point projects need FFT support):
one int32 radix-4 kernel with Q1.30 twiddles and shift-before-multiply,
Q15 as an I/O width with two guard bits, fixed and block-floating
scaling policies with both directions' scales as header numbers, its
own inverse scaling, Ooura's real post-pass formulas so the packing and
sign convention are one contract. D1-D3 settled accordingly.

Adds Part 8 (documentation plan: header contract with pinned-by test
names, docs/fft-design.md, README profiles table, provenance, CLAUDE.md,
capi + executed fft notebook), Part 9 (test plan: per-file batteries,
parity target with its own fp-contract flags, independent oracle,
fixed-point battery, RT guard, rules), and Part 10 (embedded CI:
Cortex-M4 soft-float and M4F on mps2-an386, M33 on mps2-an505, M55 on
mps3-an547, platform files with the MSPLIM write guarded for Armv7E-M,
one-shot gtest harness, size and instruction-count gates).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy
Stage 1b and Part 11: bench/icount scenarios per profile and size, one
deterministic binary each, baselines seeded from the vendored C on every
QEMU leg before the routing flip, QEMU TCG instruction counts ratcheted
at +/-3% per target as a failing check, .text ceilings in the same job,
host wall-clock informational only. Stage 2b is gated on port-vs-C,
Stage 3b seeds the fixed-point scenarios, Stage 4 gets m55 and
m55-ooura keys so a backend regression is visible. D11 records it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy
…m rules) to the FFT plan

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy
Part 13 records the findings that change the plan rather than a PR:
negative on-target test filters, visible CI output for informational
and fingerprint targets, an integer bench checksum with seeding only
from main, SMMULR is not a bit-exact seam for mul_coeff, the arithmetic
trait docstring as the 3b spec, the spectrum view not foreclosing
integer types, fingerprint tooling in both repos, corrected licensing
facts about the vendored Ooura file and WebRTC's broader notice,
branch protection, and the capi defects' owning stage. D6 settles that
readme.txt stays at third_party/ooura permanently.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy
tap added a commit that referenced this pull request Sep 17, 2026
…ews (#18)

NOTICE.md (canonical): the vendored fftsg.c is not "unmodified" — upstream
carries no notice (it lives only in readme.txt), the banner on the vendored
copy is Tap's, trailing whitespace is stripped, and DspTap ships 2 of the
package's files; state that, soften "which the distribution grant covers" to
the maintainer's reading, add the judgement-call caveat, drop the uncited
"informally reported lack of objection", and describe WebRTC's precedent as
what it is: a broader notice in their LICENSE that is not in fft.tgz and
that DspTap does not rely on. Owned-path list now covers everything outside
third_party/. LicenseRef-Ooura resolves to LICENSES/LicenseRef-Ooura.txt
(readme.txt lines 140-145 verbatim). readme.txt stays at third_party/ooura/
permanently; only fftsg.c moves at 2c (D6 as amended).

docs/fft-design.md: points at NOTICE as canonical and gives the reasoning;
same fact corrections; two profiles today, Q15/Q31 planned; the 1.105e-7 /
1.19e-7 / 1.114e-7 values labelled as the audit's Part 6 N2 probe, pinned at
Stage 2a; Oppenheim & Schafer cited with edition and section; Stage 3a -> 3b
for the platform-independent table; Welch derivation (3b) split from the
notebook numbers (3c); consumer follow-ups list (MuTap THIRD_PARTY_NOTICES at
2c, itu-compliance glossary at 2b, ci.yml header-only at 2c, MuTap-Max
transitive); banner restructured with the four house lines first and tagged
as a documented exception; email addressed to the author's current Kyoto
address first, "Dr.", no bounce prediction, corrected description of what
DspTap ships, and the question about WebRTC's broader wording; forward-link
note for the plan PR (#25).

README.md: Provenance/License aligned with NOTICE; VENDOR.md: the one stale
MUTAP_FFT_CMSIS -> TAP_DSP_FFT_CMSIS (Tap-authored file, not vendored source).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy
@tap
tap merged commit f56f587 into main Sep 17, 2026
12 checks passed
tap added a commit that referenced this pull request Sep 17, 2026
* docs: precise Ooura licensing statement, stale-name fixes, and the FFT design-note skeleton

NOTICE.md: fix include/dsptap/ -> include/tap/dsp/ and DSPTAP_FFT_CMSIS ->
TAP_DSP_FFT_CMSIS; replace "permissive/public" with Ooura's notice quoted
verbatim and a statement of what it grants (use, copy, modify; distribution of
the ORIGINAL package), what DspTap ships today (the original), and what the
forthcoming C++ port relies on (the modification grant; it is a derivative
work, not the original package); SPDX plan LicenseRef-Ooura AND MIT for the
port header, MIT elsewhere; readme.txt stays in-tree permanently.

docs/fft-design.md: the design-note skeleton per audit Part 8 item 2, with
every measurement-dependent entry marked TODO(stage N): per-profile contract
table (double/float filled from fft.h and its tests, Q15/Q31 from the Part 7
design), the split-radix vs radix-4-int32 rationale with the Welch 1969 and
Oppenheim & Weinstein 1972 references, the fp-contraction policy, the
transliteration rules, empty per-target size and icount tables, the
provenance and licensing statement with the port header's banner ready to
paste, a draft email to the address in Ooura's notice marked for the
maintainer to send (nothing sent), and an empty contract-changelog table.

README.md: Provenance and License sections aligned with NOTICE; one sentence
pointing at docs/ for the port plan and design note. Nothing is claimed to
have landed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy

* docs: correct the Ooura licensing facts after the wave-1 hostile reviews (#18)

NOTICE.md (canonical): the vendored fftsg.c is not "unmodified" — upstream
carries no notice (it lives only in readme.txt), the banner on the vendored
copy is Tap's, trailing whitespace is stripped, and DspTap ships 2 of the
package's files; state that, soften "which the distribution grant covers" to
the maintainer's reading, add the judgement-call caveat, drop the uncited
"informally reported lack of objection", and describe WebRTC's precedent as
what it is: a broader notice in their LICENSE that is not in fft.tgz and
that DspTap does not rely on. Owned-path list now covers everything outside
third_party/. LicenseRef-Ooura resolves to LICENSES/LicenseRef-Ooura.txt
(readme.txt lines 140-145 verbatim). readme.txt stays at third_party/ooura/
permanently; only fftsg.c moves at 2c (D6 as amended).

docs/fft-design.md: points at NOTICE as canonical and gives the reasoning;
same fact corrections; two profiles today, Q15/Q31 planned; the 1.105e-7 /
1.19e-7 / 1.114e-7 values labelled as the audit's Part 6 N2 probe, pinned at
Stage 2a; Oppenheim & Schafer cited with edition and section; Stage 3a -> 3b
for the platform-independent table; Welch derivation (3b) split from the
notebook numbers (3c); consumer follow-ups list (MuTap THIRD_PARTY_NOTICES at
2c, itu-compliance glossary at 2b, ci.yml header-only at 2c, MuTap-Max
transitive); banner restructured with the four house lines first and tagged
as a documented exception; email addressed to the author's current Kyoto
address first, "Dr.", no bounce prediction, corrected description of what
DspTap ships, and the question about WebRTC's broader wording; forward-link
note for the plan PR (#25).

README.md: Provenance/License aligned with NOTICE; VENDOR.md: the one stale
MUTAP_FFT_CMSIS -> TAP_DSP_FFT_CMSIS (Tap-authored file, not vendored source).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZPTzNxo5Fe4EtpXXKf7Sy

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
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