Skip to content

[fft] Exploit bivariate padding structure in transforms - #88

Open
devin-ai-integration[bot] wants to merge 1 commit into
devin/1786977962-fused-graeffefrom
devin/1786977962-padded-transform
Open

[fft] Exploit bivariate padding structure in transforms#88
devin-ai-integration[bot] wants to merge 1 commit into
devin/1786977962-fused-graeffefrom
devin/1786977962-padded-transform

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

The Kinoshita–Li buffers are bivariate packings (y = x^C) whose stride-C rows are only half-occupied, i.e. zero wherever (j mod C) >= C/2 — a 2D convolution zero-padded in x. This prunes the FFTs on both sides of that structure, cutting a constant factor off the leading n log² n transform work (the generalization of the earlier evens-upsample trick from b=0 to arbitrary strides).

New engine primitives (documented in the engine contract, required by the concept):

  • E::transform_padded(in, n, C) — transform of an input zero on the dead columns. In fft_core::forward_padded, the cross-row DIF stages (k >= C) only touch the live columns (half work), and the stage pairing (j, j+C/2) reads known zeros so it degenerates to copy+twiddle; stages below run in full. Output is the ordinary full transform, so it composes with everything else.
  • E::finish_padded(p, out, C, op) — finish when only the live outputs are wanted; fft_core::inverse_padded is the exact mirror (output-pruned inverse), and the dead positions of out are left unspecified. Valid for any product spectrum, since it's output pruning, not an input-support assumption.

Implemented for ntt, real (packing pairs adjacent x's, so the row structure survives at stride C/2 in the packed buffer; C == 2 falls back to the dense path), split, crt, and forwarded through componentwise (matrix/trunc/stable get it for free, with the non-assign op composed through an element buffer as in finish).

Call sites:

// packed_bivariate::advance — Q's x-truncation zeroes the top half of each row
auto tq = E::transform_padded(c, B, 2 << (L - l));
E::finish_padded(E::graeffe(tq, B), c.first(B/2), 1 << (L - l));

// ps_compose pushdown — P's parity mask has the same shape, and the next
// level's mask re-zeroes exactly the positions finish_padded left unspecified
auto tp = E::upsample(E::transform_padded(P.first(B/2), B/2, 1 << (L - l)), B, false);
if (l > 0) E::finish_padded(E::mul(tneg[l], tp, B), P, 2 << (L - l));
else       E::finish(E::mul(tneg[l], tp, B), P);

Tests: all-engine transform_padded/finish_padded equivalence against the plain transform/finish (including the add_op path), plus the same for the matrix/trunc/stable wrapper engines; the existing compose tests cover the series call sites.

Stacked on #87 (uses E::graeffe); base is that branch and should retarget to master once it merges.

Link to Devin session: https://app.devin.ai/sessions/7d41aa62f31e4620807608a6e6afcc94
Requested by: @ecnerwala


Open in Devin Review (Beta)

@ecnerwala ecnerwala self-assigned this Aug 17, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1786977962-fused-graeffe branch from c6d77ef to 095004b Compare August 17, 2026 16:47
Co-Authored-By: Andrew He <he.andrew.mail@gmail.com>
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1786977962-padded-transform branch from 822acbd to 2a6086c Compare August 17, 2026 16:50
@github-actions

Copy link
Copy Markdown

GCC Code Coverage Report

📂 Overall coverage

Metric Coverage
Lines 🟡 8763/10590 (82.7%)
Functions 🟢 1211/1318 (91.9%)
Branches 🟡 6933/8821 (78.6%)

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