rational M5: the fixed-point profiles, measured per stage - #60
Merged
Merged
Conversation
The stage has been format-generic since M3 (tap::dsp::sample_traits); M5 is the battery that states each format's contract as numbers, for every ratio of the vocabulary at every named profile (tests/test_fixed_point.cpp): - every phase row, and every decimator's whole filter, sums to exact unity in Q15 and Q31, so full-scale DC of either sign is exactly full scale from every phase; - the Q15 and Q31 tables are bit-pinned (FNV-1a-64, 112 pins); - no structural zero enters the dot of an interpolator, a decimator or a mixed ratio going up; float and Q31 count the design's nonzero taps, Q15 its quantized span (pinned per stage; the 120 dB designs' outer taps round to zero in Q1.14 and are trimmed); - Q31 tracks double within 3.4e-9 of full scale, a decade under float (5.1e-8; bridge's floor is 5e-8); - Q15's RMS deviation from double (-85.6 to -95.8 dBFS) and the stopband its quantized table attains are pinned per stage; - +-full-scale noise saturates and never wraps (within 8.8e-4 / 1.6e-8 of the clamped double model); chains stack the floors stage by stage. Two honest limits, stated in PLAN.md section 6 and pinned: a Q15 decimator's table is h / M on the same Q1.14 LSB, so its attained stopband loses about 20 log10 M dB (by 6 at economy -64.7 dB, by 8 -62.9 dB; Q15's pairing is economy, transparent buys nothing there); and a mixed ratio going down (2/3, 3/4, 3/8) runs L-phase rows over a band-M design and multiplies the band's zeros its rows cross (20 of 65 MACs per superblock for 2/3). Both levers are deferred with the codegen levers after M6. The quantized-stopband test is a host suite (a 16384-point DFT over 112 tables), excluded on the QEMU legs and Hexagon. Plan v0.8; the stage header, READMEs and CLAUDE files follow. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
Milestone M5 of
rational/PLAN.md:tests/test_fixed_point.cpp, a battery that states the Q15 and Q31 contract of every ratio of the vocabulary at every named profile as numbers. The plan goes to v0.8 with a measured per-stage table and two stated limits. No engine code changes; the stage has been format-generic since M3.Why
M5's acceptance asks for Q31 within float's floor, Q15's format-limited numbers stated per stage, exact-unity row sums, wrap safety, the structural zeros out of the dot and bit-pinned tables. The datapaths already existed, so this PR measures them and pins what it finds, including two things that do not meet the 70 dB promise in Q15.
Verification
FixedPoint.EveryRowSumsToExactUnityInBothFormats: every phase row, and every decimator's whole filter, sums to 2^14 / 2^30.FixedPoint.TablesAreBitPinned: FNV-1a-64 per ratio, profile and format, 112 pins.FixedPoint.StructuralZerosNeverEnterTheDot: no design zero inside the trimmed span of any interpolator, decimator or mixed-up stage. Float and Q31 MACs equal the design's nonzero count; Q15 MACs are pinned per stage.FixedPoint.Q31TracksDoubleAndQ15IsTheFormatFloor: worst |Q31 − double| 3.4e−9 against float's 5.1e−8. Q15 RMS deviation −85.6 to −95.8 dBFS, pinned per stage within 1 dB.FixedPoint.QuantizedTablesAttainTheirStatedStopbands(host only): Q31 keeps the design's stopband; Q15's attained stopband is pinned per stage within 0.5 dB.FixedPoint.FullScaleNoiseSaturatesNeverWraps: ±full-scale noise lands within 8.8e−4 (Q15) and 1.6e−8 (Q31) of the clamped double model.FixedPoint.FullScaleDcIsExactFromEveryPhaseandFixedPoint.ChainsStackTheFloorStageByStage.-Werror(278 of 278), the fixed-point battery with GCC,scripts/tidy.shclean, clang-format clean, the Cortex-M33 one-shot (87 tests, 87 s) and the Cortex-M55 one-shot (7 s). Hexagon runs in CI; its rational row now also excludes the stopband test.Notes for the reviewer
economy, ↓6 reaches −64.7 dB and ↓8 −62.9 dB; ↓2 and ↓3 hold 70.transparentbuys nothing in Q15. A lever (per-branch unity tables with the 1/M folded into the finalize) is recorded in the plan and deferred to the codegen phase after M6, since it changes the pinned tables and the rounding point.economy. The matrix's MAC figures already count this. Sparse rows are a deferred lever too.🤖 Generated with Claude Code
https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
Generated by Claude Code