Truncated FFTs
- Cost
- At most butterflies (or additions) for of points, forward and inverse.
A convolution with radix-2 FFTs uses a transform length at least as large as the length of the product. Rounding up to a power of two can double the work: a product of length costs as much as one of length . (A middle product can use a shorter length, since the wrap-around may fall outside the coefficients it needs; see Classical and FFT middle products.) The truncated Fourier transform (TFT) of van der Hoeven [vdH2004; vdH2005] computes only of the values, and its inverse recovers a polynomial of length from them, in time proportional to rather than . Harvey made it cache-friendly [Har2009], Harvey and Roche [HR2010] and Arnold [Arn2013] gave in-place variants.
FLINT uses truncated transforms in both of its integer FFTs: fft.h implements van der Hoeven's recursion in fft_truncate and ifft_truncate (and their sqrt2 and matrix Fourier variants), and fft_small implements Harvey's version with separate input and output truncation in sd_fft_trunc and sd_ifft_trunc, and their transposes in sd_fft_trunc_tr and sd_ifft_trunc_tr (Transposed transforms). The algorithms are stated below in the form used by fft.h, with proofs.
Notation#
Let be a commutative ring, , , and let satisfy , with invertible in . (In fft.h, and or ; see The ring.) Let be the integer whose binary digits are those of reversed. For and , define
the transform in bit-reversed order that fft_radix2 computes by radix-2 decimation in frequency (Algorithm 1 of Discrete Fourier transforms over a generic ring). The values at positions below are the first values.
Lemma 1 (Splitting). For let and . With the transforms of length taken with respect to ,
Proof. For , and . Let . Since , . Since , .
The splitting is one layer of decimation-in-frequency butterflies [GS1966]; applied recursively it gives fft_radix2. Truncation consists in skipping all work whose results are not among the first values.
The forward transform#
fft_truncate1)Input: ; an even with .
Output: .
- If , compute the full transform.
- If : set for and return the first values of the transform of (recursively, with ).
- Otherwise: compute and by butterflies, compute the full transform of , and return it followed by the first values of the transform of (recursively).
fft_truncate)Input: (and for ); an even with .
Output: .
- If , compute the full transform.
- If : then , so return the first values of the transform of , recursively with zero padding.
- Otherwise: for compute by a butterfly; for , where , set and . Compute the full transform of and the first values of that of by Algorithm 1.
Both are correct by Lemma 1 and induction on . In step 3 of Algorithm 2 the vector is in general not zero-padded, which is why the recursion switches to Algorithm 1.
Theorem 2 (Cost). Algorithm 1 and Algorithm 2 use at most butterflies, additions or multiplications by powers of .
Proof. Let be the worst count, and for the full transform. If , the count is at most . If , it is at most . We show by induction. The case is clear. If , by induction . If , .
The full transform costs , so for just above the truncated transform costs about half. In practice the additive term is smaller than the bound suggests, since Algorithm 2 does not add anything in step 2.
The inverse transform#
The inverse must recover from when for . Since the evaluation points , , do not form a subgroup, this is an interpolation problem, but the splitting lemma reduces it to the same recursion if, at each level, the missing values of one half are reconstructed from the other. The general step works with a mixed vector that holds transform values at the positions below and (scaled) coefficients at the positions from on.
ifft_truncate1)Input: for and for ; an even with .
Output: for .
- If , apply the full inverse transform, which gives .
If :
- for : ;
- apply the algorithm recursively to with (length , root );
- for : .
If :
- apply the full inverse transform of length to ;
- for : , , ;
- apply the algorithm recursively to with ;
- for : .
Theorem 3. Algorithm 3 is correct: on return, for .
Proof. Induction on ; let , be as in Lemma 1, and note that the inverse transform of length returns times its argument.
Case . After step 2.1, for , , while for , . This is valid input for length , so after step 2.2, for . Since , was given, and step 2.3 yields .
Case . The first values are , so step 3.1 gives for all . For , the position holds , so ; step 3.2 sets and , which is final. Now the second half holds at its positions and at its positions , valid input for length , so after step 3.3 it holds for . Finally, since , step 3.4 turns into .
ifft_truncate)Input: , where for ; an even with .
Output: .
- If , apply the full inverse transform.
- If : then with zero padding; recursively obtain for and double them.
- If : apply the full inverse transform of length , giving ; for , where and so , set ; apply Algorithm 3 to the second half with ; apply the inverse butterflies for and double for .
Theorem 4 (Inversion). If for , then determine , and Algorithm 4 computes from them. Both inverse algorithms use at most butterflies, additions, halvings and multiplications by powers of .
Proof. Algorithm 4 is Algorithm 3 with the known values for substituted: in step 2, makes the first loop trivial and the last one a doubling; in step 3, , so and the final value is a doubling, which can be done at the end. Correctness follows from Theorem 3, and the algorithm shows that the values determine , since is invertible. For the cost, the loops of step 2 take operations in total, and those of step 3 take operations besides the transform of length , so the count satisfies the recursion of Theorem 2.
To multiply polynomials and whose product has length at most , one therefore computes the first values of and , multiplies them pointwise (these are the first values of the transform of , because ), and applies the inverse TFT. This is fft_convolution: the product costs about butterflies instead of , and its running time grows smoothly with .
Use in FLINT#
fft_truncate,fft_truncate1,ifft_truncateandifft_truncate1are Algorithm 2, Algorithm 1, Algorithm 4 and Algorithm 3 with modulo ; the halving in step 2.1 of Algorithm 3 ismpn_div_2expmod_2expp1with . FLINT requires to be even, since its recursion bottoms out at length 2 with ; the callers round up.fft_truncate_sqrt2andifft_truncate_sqrt2use length with and require : they always perform the first layer in the form of step 3 (with the twiddles), a full transform of length on the first half and a truncated one on the second.- The matrix Fourier functions truncate at whole rows: the number of points is rounded up to a multiple of , where is the row length, so the row transforms are complete and only the column transforms of the second half are truncated, by
fft_truncate1_twiddleandifft_truncate1_twiddle; see Truncation. fft_smalluses the more general form of Harvey [Har2009]:sd_fft_trunctakes separate truncations for the input (coefficients known to be zero fromitruncon) and the output (values wanted belowotrunc), and the inversesd_ifft_truncis a recursion in terms of the number of possibly nonzero coefficients, the number of known values and a flag asking for one more value, which Algorithm 3 specialises to and . There the truncation works in blocks of 256 points and is combined with a decomposition into rows and columns as in the matrix Fourier algorithm. See FFTs modulo word-size primes in floating point.
Referenced from#
- FFTs in FLINT (overview)
- Discrete Fourier transforms over a generic ring (algorithm)
- The matrix Fourier algorithm (algorithm)
- Schönhage–Strassen multiplication (algorithm)
- FFTs modulo word-size primes in floating point (algorithm)
- Multiplying polynomials over Z/nZ (overview)
- Convolutions of large integers
- fft.h (module)
- Multiplying large integers
- Radix-2 and truncated transforms
References#
- [vdH2004] J. van der Hoeven, "Truncated FFTs", ISSAC 2004 notes, https://www.texmacs.org/joris/issac04/issac04.html
- [vdH2005] J. van der Hoeven. Notes on the truncated Fourier transform. Technical report 2005-5, Université Paris-Sud, Orsay, 2005.
- [Har2009] D. Harvey. A cache-friendly truncated FFT. Theoretical Computer Science 410 (2009), 2649–2658.
- [HR2010] D. Harvey and D. S. Roche. An in-place truncated Fourier transform and applications to polynomial multiplication. ISSAC 2010, 325–329.
- [Arn2013] A. Arnold. A new truncated Fourier transform algorithm. ISSAC 2013, 15–22.
- [GS1966] W. M. Gentleman and G. Sande. Fast Fourier transforms – for fun and profit. AFIPS Fall Joint Computer Conference 29 (1966), 563–578.
The FLINT team, “Truncated FFTs,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/fft/truncated-fft.html (generated 2026-11-02).
@misc{flint-doc-algorithms-fft-truncated-fft,
author = {{The FLINT team}},
title = {{Truncated FFTs}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/fft/truncated-fft.html},
note = {Generated 2026-11-02}
}