Middle products and the transposition principle
- Cost
- A middle product of lengths and (output length ) costs multiplications classically and about one product of lengths and with the FFT.
Many algorithms need only a window of the coefficients of a product. The most important case is the middle product: given of length and of length , the coefficients of of index to . These are exactly the coefficients in which every coefficient of meets a coefficient of . The middle product is the transpose of multiplication, and the transposition principle says that it can be computed as fast as a product of lengths and , although the full product has length . The middle product was named and systematically studied by Hanrot, Quercia and Zimmermann [HQZ2004]. The transposition principle comes from Tellegen's work on electrical networks and was brought into algebraic complexity by Fiduccia [BCS1997, Ch. 13]; Shoup [Sho1995] and Bostan, Lecerf and Schost [BLS2003] made systematic use of it for polynomial algorithms.
FLINT generalises the notion: _nmod_poly_mulmid computes coefficients of a product of any lengths, so that mullow is the case and mul the case , .
Generic version#
gr_poly_mulmid computes the window of a product over any ring through the ring method GR_METHOD_POLY_MULMID. Rings with a fast multiplication supply a middle product with it: nmod uses _nmod_poly_mulmid as described below, and fmpz, fmpq, fmpz_mod, mpn_mod, the fq family, the ball rings, fmpzi and polynomial rings (by bivariate Kronecker substitution) have their own methods. The default _gr_poly_mulmid_generic computes the low product of length with the ring's mullow method and discards the first coefficients when that method is not the classical default, and otherwise uses the classical middle product, which computes only the requested coefficients with one dot product each. The generic Newton iterations (Generic version) check whether the ring has its own middle product and use it only in that case, since the fallback through a low product gains nothing.
The transposition principle#
A linear straight-line program computes for a fixed matrix by a sequence of additions, subtractions and multiplications by constants applied to the inputs and to earlier results. Its length is the number of such operations.
Theorem 1 (Tellegen's principle). If has no zero rows and no zero columns and is computed by a linear straight-line program of length , then is computed by a linear straight-line program of length .
Proof. (Sketch; see [BCS1997, Ch. 13] for details.) Represent the program as a directed acyclic graph whose vertices are the inputs, the intermediate results and the outputs, with an edge, weighted by the constant factor, from each operand of an operation to its result. Then is the sum, over all paths from input to output , of the products of the weights. Reversing every edge gives a graph in which the same sums describe ; the multiplications by constants stay on their edges. A vertex with incoming edges costs additions, so with edges and vertices the original program has additions, the sum running over all vertices except the inputs. In the reversed graph the in-degrees are the original out-degrees and the sources are the outputs, so it has additions. The hypothesis on ensures that no input or output is isolated.
The principle turns any algorithm for a linear map into one for its transpose with essentially the same cost. Transposing an algorithm by hand is mechanical but error-prone; [BLS2003] give a methodology and many examples.
Middle product as transposed multiplication#
For a fixed of length , multiplication by is the linear map , , whose matrix is a Toeplitz matrix.
Lemma 2. for of length , and these are the coefficients of , where .
Proof. The entry of in row and column is (zero outside ), so . On the other hand, , which is the same sum with .
By Theorem 1, any algorithm that multiplies polynomials of lengths and yields an algorithm for the middle product with essentially the same number of operations. [HQZ2004] give explicit transposed versions of Karatsuba's and the FFT algorithms; for the FFT the transposed algorithm is particularly simple, as shown next.
Classical and FFT middle products#
The classical middle product computes each requested coefficient as a dot product, multiplications in total for the HQZ middle product. In FLINT these dot products use the delayed reduction of Dot products modulo a word-size integer (_nmod_poly_mulmid_classical).
An FFT computes products modulo , that is cyclic convolutions, and a middle product only needs a convolution length large enough for the wrap-around to miss the requested window.
Lemma 3 (Wrap-around). Let have length and let . If and , then coefficients to of equal those of .
Proof. Coefficient of is . For we have and , so only the term is nonzero.
For the HQZ middle product, , and , so any with works: the transforms then have the length of the longer operand, as for a product of lengths and , instead of the length of the full product. A radix-2 FFT needs to be a power of two, which need not exist in that range (for the range is ); a truncated transform of length below does not compute a product modulo . The transposed FFT (Transposed FFT) has no such restriction.
Input: of length , of length , a window of the product, of length .
Output: coefficients of .
- If there is a power of two with , take it. Otherwise take a transform length (no wrap-around).
- Compute the forward transforms of and of length , multiply pointwise, and transform back.
- Return coefficients to of the result.
Correctness is Lemma 3. This is what fft_small does in _nmod_poly_mul_mid_mpn_ctx (via _fft_small_plan_set_window_nmod), with truncated transforms rounded to blocks of 256 when there is no suitable power of two; Windows and wrap-around treats the same wrap-around for windows of integer products. Each transform is computed modulo one to four primes and the results are combined by Chinese remaindering, as for ordinary products (The small-prime FFT).
Transposed FFT#
The transposition principle can also be applied to the FFT product itself. Fix of length and an output length , and let be the truncation of a transform of length . Multiplication by is computed as
where evaluates a polynomial of length at the first points (a truncated forward transform), multiplies pointwise by the transform of and a normalising constant, is the truncated inverse transform of length , and keeps the first coefficients.
Theorem 4 (Transposed convolution). With this notation, , where pads a vector of length with zeros to length . Hence computes the middle product of Lemma 2 with the transforms of a product of lengths and , and the transposed transforms and cost as much as and .
Proof. The factorisation of holds as an identity of linear maps, because the truncated transforms compute the product exactly for every input of length once . Transposing reverses the order of the factors, and is diagonal. The transforms are linear straight-line programs (butterflies, copies and zeroings), so by Theorem 1 their transposes are computed by programs of the same length; in fact each butterfly is replaced by its transpose and the order of the butterflies is reversed, which gives the same numbers of additions and multiplications.
Input: of length , of length at most .
Output: for (with padded with zeros); for these are coefficients to of .
- Choose the transform length and truncation of a product of lengths and .
- Compute the forward transform of (input truncation , output truncation ).
- Pad to length and apply the transposed inverse transform.
- Multiply pointwise by and the normalising constant.
- Apply the transposed forward transform with input truncation (it reads values and writes ) and return its first entries.
Correctness is Theorem 4. Compared with Algorithm 1, the transform length is that of a product of lengths and for every and , not only when a power of two lies in . No wrap-around is used: the transpose of a cyclic convolution is a cyclic correlation, which is not the middle product. The same idea gives transposed versions of every FFT-based multiplication, see [BLS2003] and, for the truncated Fourier transform, [vdH2004].
In FLINT, sd_fft_trunc_tr and sd_ifft_trunc_tr are the transposes of the truncated transforms of fft_small (Transposed transforms), and _nmod_poly_mul_tr_mpn_ctx is Algorithm 2 modulo one to four primes with Chinese remaindering. _nmod_poly_mulmid_fft_small computes a window as a window of the full product with Algorithm 1 or as a transposed product, whichever has the strictly shorter transform; the former wins only when its wrap-around reaches the same length, where it is a few percent faster. For the balanced middle product (, as in Newton iteration) without a power of two in , the transform shrinks from about to points.
The same reduction applies to any window of a product of lengths and . First the coefficients of the operands that no output coefficient uses are dropped: those of index at least , and the low coefficients of each operand that meet the other one only below . Let then of length be the shorter operand, of length the longer one and . Coefficient of is with (zero outside ), a transposed product of lengths and . When this costs a product of the shorter operand and the window instead of a product of both operands; since the operands enter symmetrically, they may be given in either order. _nmod_poly_mulmid_fft_small, the integer windows of _mpn_ctx_mpn_mul_range (on the polynomials of chunks, see Algorithm) and radix_mulmid_fft_small use it whenever and its transform is strictly shorter than that of Algorithm 1. The integer versions skip it for squarings, and the nmod_poly version also requires that the window does not extend beyond the full sums on both sides.
The transposed product is bilinear in and , so either factor can be prepared in advance. When is fixed and many short are applied to it, storing leaves two transforms per product, and , against three for the plain transposed product, and also for Algorithm 1 with a stored transform of . The transform length then depends only on (in fft_small, rounded up to a multiple of 256, instead of a power of two or the length of the full product). This is _mul_precomp_init_tr with _nmod_poly_mul_tr_precomp, used for the middle products of evaluation and extrapolation at geometric progressions (Geometric progressions).
Kronecker substitution has no such shortcut in FLINT: _nmod_poly_mulmid_KS drops the operand coefficients that cannot contribute to the window and then forms the whole integer product.
Uses#
Newton iteration. When approximates to terms, the first coefficients of are known in advance (), and the next step needs only coefficients to . With truncated to length this is a middle product with output length , costing about one product of length instead of a product of lengths and . The same saving appears in division, square roots and exponentials; see Newton iteration for power series and division.
Geometric progressions. Evaluating a polynomial at the points reduces, by Bluestein's chirp trick, to a single middle product (Geometric progressions).
Transposed algorithms. Transposing multipoint evaluation gives the "transposed remainder tree" of [BLS2003] and Bernstein's scaled remainder tree [Ber2008], and transposing modular multiplication gives Shoup's power projection [Sho1995], used in minimal polynomial and factoring algorithms. FLINT's nmod_poly does not currently use these transposed variants: multipoint evaluation uses the ordinary remainder tree (Multipoint evaluation and interpolation).
Use in FLINT#
_nmod_poly_mulmidandnmod_poly_mulmidcompute any window of a product, choosing between the classical method, Kronecker substitution,_nmod_poly_mul(for the full window) and the FFT, see Cutoffs. The forced variants are_nmod_poly_mulmid_classical,_nmod_poly_mulmid_KSand_nmod_poly_mulmid_fft_small; the last one chooses between Algorithm 1 (_nmod_poly_mul_mid_default_mpn_ctx) and Algorithm 2 (_nmod_poly_mul_tr_default_mpn_ctx).- In
fft_small,fft_small_ifft_tr_nmodandfft_small_fft_trgive the transposed transforms on transformed operands (Transposed products), and_mul_precomp_init_trwith_nmod_poly_mul_tr_precompthe transposed product with a stored . The integer middle productsflint_mpn_mulmid(through_mpn_ctx_mpn_mul_range) andradix_mulmid(throughradix_mulmid_fft_small) use Algorithm 2 for short windows as described above; thefmpz_polyandmpn_modmiddle products offft_smalluse only Algorithm 1. - The
grcontext for installs_nmod_poly_mulmidas its middle product method. The generic Newton iterations ofgr_poly(_gr_poly_inv_series_newton,_gr_poly_div_series_newton,_gr_poly_rsqrt_series_newton,_gr_poly_sqrt_series_newton,_gr_poly_exp_series_newton), whichnmod_polycalls for long series, use a middle product whenever the ring provides one, and a low product followed by discarding coefficients otherwise. nmod_poly_evaluate_geometric_nmod_vec_fastandnmod_poly_extrapolate_geometricare each one middle product plus linear work; with a precomputation made with bit 3 offunctionset (_nmod_geometric_progression_init_function), these middle products use a stored .fmpz_poly_mulmidprovides the same operation over .
void _nmod_poly_mulmid(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, slong nlo, slong nhi, nmod_t mod)void nmod_poly_mulmid(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong nlo, slong nhi)void _nmod_poly_mulmid_classical(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, slong nlo, slong nhi, nmod_t mod)void _nmod_poly_mulmid_KS(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, slong nlo, slong nhi, nmod_t mod)Referenced from#
- Power series in ball arithmetic (algorithm)
- FFTs in FLINT (overview)
- Multiplication with several primes and CRT (algorithm)
- FFTs modulo word-size primes in floating point (algorithm)
- Truncated FFTs (algorithm)
- Multiplying integers (overview)
- High, low and middle products of integers (algorithm)
- Multiplying polynomials over Z (overview)
- Multiplying polynomials over Z/nZ (overview)
- Newton iteration for power series and division (algorithm)
- Polynomial arithmetic over generic rings and its specialisations (overview)
- Multipoint evaluation and interpolation (algorithm)
_arb_poly_mulmid_classical,_arb_poly_mulmid_block,_arb_poly_mulmid,arb_poly_mulmid_classical,arb_poly_mulmid_block,arb_poly_mulmid- Multiplying polynomials with ball coefficients
_nmod_poly_mul_tr_mpn_ctx,_nmod_poly_mul_tr_default_mpn_ctx- Multiplying large integers
- Multiplying polynomials
- Products and divisions with a fixed operand
- Transforms modulo one prime
- Arithmetic in transform space
- Multiplying polynomials
_gr_poly_mulmid,gr_poly_mulmid- nmod_poly.h (module)
_nmod_poly_mulmid,nmod_poly_mulmid_nmod_poly_mulmid_fft_small,_nmod_poly_mullow_fft_smallnmod_geometric_progression_init,_nmod_geometric_progression_init_function- Power series inversion and division
- Multiplying polynomials
radix_mulmid_classical,radix_mulmid_fft_small,radix_mulmid_KS,radix_mulmid_naive
References#
- [HQZ2004] G. Hanrot, M. Quercia and P. Zimmermann, "The middle product algorithm I. Speeding up the division and square root of power series", Applicable Algebra in Engineering, Communication and Computing 14:6 (2004), 415–438
- [BCS1997] P. Bürgisser, M. Clausen and M. A. Shokrollahi, Algebraic Complexity Theory, Grundlehren der mathematischen Wissenschaften 315, Springer (1997)
- [Sho1995] V. Shoup, "A new polynomial factorization algorithm and its implementation", Journal of Symbolic Computation 20:4 (1995), 363–397
- [BLS2003] A. Bostan, G. Lecerf and É. Schost, "Tellegen's principle into practice", ISSAC 2003, 37–44
- [vdH2004] J. van der Hoeven, "Truncated FFTs", ISSAC 2004 notes, https://www.texmacs.org/joris/issac04/issac04.html
- [Ber2008] D. J. Bernstein, "Fast multiplication and its applications", in Algorithmic Number Theory, MSRI Publications 44 (2008), 325–384
The FLINT team, “Middle products and the transposition principle,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/polynomials/middle-product.html (generated 2026-11-02).
@misc{flint-doc-algorithms-polynomials-middle-product,
author = {{The FLINT team}},
title = {{Middle products and the transposition principle}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/polynomials/middle-product.html},
note = {Generated 2026-11-02}
}