Strassen–Winograd multiplication
- Cost
- operations for matrices; one level costs 7 products of half size and 15 additions of quarter-size blocks.
Strassen showed that two matrices over any ring can be multiplied with 7 multiplications instead of 8 [Str1969]. Since the entries can themselves be matrices, applying the scheme recursively multiplies matrices in ring operations. Winograd's variant [Win1971] needs 15 block additions instead of 18. The version described below is that of nmod_mat_mul_strassen, which is also used, in byte or bit-packed form, by nmod_mat_mul_u8.
Generic version#
gr_mat_mul_strassen performs one level of the Winograd form of Strassen's algorithm over any ring, in Bodrato's order of operations, computing the seven block products with gr_mat_mul and handling odd dimensions by peeling off the last row or column. Recursion therefore happens only through the ring's matrix multiplication method: a ring installs a method that calls gr_mat_mul_strassen above a cutoff and a base-case product below it, as the context nmod32 does on top of the 32-bit SIMD kernel of nmod_mat. The scheme needs no commutativity, so it also applies to matrices over noncommutative rings and to block matrices. The same seven-product formulas multiply the matrices of polynomials in the half-gcd algorithm of gr_poly (Half-GCD) once their entries have length 20 or more.
The formulas#
Split (), () and into blocks , , of compatible sizes. FLINT uses the sequence of Bodrato [Bodrato2010], which is equivalent to Winograd's and was designed so that the same operands serve for squaring. With
the blocks of the product are
Theorem 1. These formulas give over any ring, commutative or not.
Proof. is immediate. Let and , so and . Then
Subtracting and leaves . Adding to instead gives, after cancellation, . Finally and , so . No step exchanges the two factors of a product, so commutativity is not used.
The operands of the products need 8 additions (, , , , , , , ) and the results 7 more, 15 in all.
Schedule and memory#
The implementation follows the memory-efficient schedule of Dumas, Pernet and Zhou [DPZ2009]: the products are written into the blocks of as they are computed, and only two temporaries are needed, of the size of (or , whichever is wider) and of the size of . With and the four blocks of as storage:
- , , ().
- , , ().
- , , ().
- , ().
- (), .
- , (final).
- ().
- , ().
- , (final).
- (), (final).
The 7 products are computed by nmod_mat_mul, so they use the fast kernels or recurse into Strassen–Winograd again, and must not be aliased with or . If any dimension is at most 4, nmod_mat_mul_strassen calls nmod_mat_mul directly.
Odd dimensions#
FLINT splits a dimension into for the top or left blocks and for the bottom or right blocks. Conceptually, the short blocks are padded with one zero row or column, so that all blocks have the same size and Theorem 1 applies. Padding with a zero row and a zero column (and accordingly) pads with zeros, so the padded product contains as its top left block. Nothing is actually padded:
- the temporaries , have the full padded size, and the sums of blocks that form them copy the extra row or column of the larger operand and write zeros beyond;
- a product with a short block of or as an operand uses the real dimensions of that block;
- the blocks , and of the real lack the padding, while the schedule stores intermediate products in them.
Proposition 2. With the schedule of Algorithm 1, the entries missing from , , are never needed for an entry of .
Proof. If is odd, and lack their last column. The final and do not read or , and the final and only need their own columns, so the missing column is not used. If is odd, and lack their last row. The last rows of the values held there (, , and the partial sums of step 9) only feed the last rows of the final and , which do not exist, except for , which is added to in step 6. But has a zero last row, because the padded and both have a zero last row. If is odd, only the temporaries and the inner dimension of are affected, and both are handled exactly as stated above.
So odd dimensions cost nothing beyond the padded additions, which touch the same entries as ordinary ones. Earlier versions of FLINT peeled off the last row or column and corrected the result with matrix-vector products, a technique known as dynamic peeling [HLJJTG1996].
Complexity#
Let be the cost for matrices when the recursion goes down to dimension . Then , so . One level replaces 8 products by 7, saving one eighth of the multiplication work, at the cost of 15 additions of entries, each of which reads and writes memory. The level pays off when a product of dimension costs more than about 15 additions of that size. With the classical algorithm, which forms one dot product per entry, this happens around dimension 200 to 400 in FLINT. With the SIMD kernels, which run at a much higher rate, the crossover FLINT_NMOD_MAT_MUL_SIMD_STRASSEN_CUTOFF is between 256 and 800, depending on the processor. The byte kernels of nmod_mat_mul_u8 recurse from dimension 256 () or 2048 (), and the bit-packed kernels for and from 8192 and 16384, since their leaves are much cheaper relative to an addition.
Numerical stability, the main concern with Strassen's algorithm in floating point, plays no role over , where all operations are exact.
Referenced from#
- Floating-point matrix multiplication (gemm) (algorithm)
- Multiplying matrices over the integers (overview)
- Multiplying matrices over Z/nZ (overview)
- Linear algebra over generic rings and its specialisations (overview)
- Matrix multiplication modulo small integers (algorithm)
- Multiplying integer matrices
gr_mat_mul_strassen- Multiplying matrices over generic rings
nmod_mat_mul_strassen
References#
- [Str1969] V. Strassen, "Gaussian elimination is not optimal", Numerische Mathematik 13 (1969), 354-356, https://doi.org/10.1007/BF02165411
- [Win1971] S. Winograd, "On multiplication of 2 × 2 matrices", Linear Algebra and its Applications 4 (1971), 381-388, https://doi.org/10.1016/0024-3795(71)90009-7
- [Bodrato2010] Bodrato, Marco : A Strassen-like Matrix Multiplication Suited for Squaring and Higher Power Computation. Proceedings of the ISSAC 2010 München, Germany, 25-28 July, 2010
- [DPZ2009] J.-G. Dumas, C. Pernet and W. Zhou, "Memory efficient scheduling of Strassen-Winograd's matrix multiplication algorithm", Proceedings of the 2009 International Symposium on Symbolic and Algebraic Computation (ISSAC) (2009), 135-143, https://doi.org/10.1145/1576702.1576713
- [HLJJTG1996] S. Huss-Lederman, E. M. Jacobson, J. R. Johnson, A. Tsao and T. Turnbull, "Implementation of Strassen's algorithm for matrix multiplication", Proceedings of the 1996 ACM/IEEE Conference on Supercomputing (1996)
The FLINT team, “Strassen–Winograd multiplication,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/linear-algebra/strassen-winograd.html (generated 2026-11-02).
@misc{flint-doc-algorithms-linear-algebra-strassen-winograd,
author = {{The FLINT team}},
title = {{Strassen–Winograd multiplication}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/linear-algebra/strassen-winograd.html},
note = {Generated 2026-11-02}
}