1. Introduction & Motivation
Multiplying two large numbers and multiplying two large matrices look like unrelated problems, yet they share an identical structural trap. Split each operand in half (numbers into a high and low part, matrices into four quadrants), and the obvious recursive strategy asks you to multiply every part of the first operand against every part of the second. For numbers split in two, that is 4 sub-multiplications. For matrices split into four quadrants, that is 8 sub-multiplications. Recursing on that plan never beats the naive method: the split adds bookkeeping overhead without changing the exponent.
Karatsuba's multiplication algorithm and Strassen's matrix multiplication algorithm both escape this trap the same way. Instead of computing every cross-term separately, they compute a smaller set of cleverly chosen combined products, then recover everything they actually need through addition and subtraction — arithmetic that is asymptotically free compared to multiplication. Karatsuba needs only 3 products instead of 4. Strassen needs only 7 instead of 8. Toom-Cook generalizes Karatsuba's idea to splits of 3 or more parts. In every case, the recurrence $T(n) = aT(n/b) + f(n)$ gets a smaller $a$, and the Master Theorem converts that smaller $a$ directly into a smaller exponent on $n$.
This lesson does not re-derive the Master Theorem step — Recursion Complete Guide already solves both of these exact recurrences. Instead, this lesson supplies what that page only gestured at: the actual split-and-combine algorithms, worked traces, full implementations, and the practical question of when these algorithms are worth using at all.
2. Prerequisites
This lesson assumes comfort with recursion, recurrence relations, and the Master Theorem, all covered in the Recursion Complete Guide. In particular:
- The Master Theorem's general form $T(n) = aT(n/b) + f(n)$ and its three cases.
- Example 3 already solves $T(n) = 3T(n/2) + O(n) = \Theta(n^{\log_2 3}) \approx O(n^{1.585})$ — the exact recurrence Karatsuba produces.
- Example 4 already solves $T(n) = 7T(n/2) + O(n^2) = \Theta(n^{\log_2 7}) \approx O(n^{2.807})$ — the exact recurrence Strassen produces.
- Basic matrix addition, subtraction, and block (quadrant) structure.
This lesson will not repeat the Master Theorem's case analysis for either recurrence; it will only cite the conclusion once each algorithm has been derived, and point back to those examples for the arithmetic.
3. A Concrete Example
Karatsuba by hand: 23 × 45
Split each 2-digit number into a high digit and a low digit: $x_1 = 2$, $x_0 = 3$, $y_1 = 4$, $y_0 = 5$. Compute three products instead of four:
| Product | Formula | Value |
|---|---|---|
| $z_2$ | $x_1 \cdot y_1 = 2 \cdot 4$ | 8 |
| $z_0$ | $x_0 \cdot y_0 = 3 \cdot 5$ | 15 |
| $z_1$ | $(x_1+x_0)(y_1+y_0) - z_2 - z_0 = (5)(9) - 8 - 15$ | 22 |
Combine: $x \cdot y = z_2 \cdot 10^2 + z_1 \cdot 10^1 + z_0 = 800 + 220 + 15 = 1035$. Direct multiplication confirms $23 \times 45 = 1035$ — the same answer, reached without ever computing $x_1y_0$ or $x_0y_1$ directly.
Notice what happened: only 3 multiplications ($8$, $15$, and $5\times9=45$) were needed, plus a few additions and subtractions. $z_1$ silently recovers the two cross terms $x_1y_0 + x_0y_1$ without computing either one separately — that algebraic substitution is the entire trick, and Section 5 explains why it works for any split size, not just single digits.
4. Naive / Brute-Force Approach
Grade-school multiplication multiplies every digit of one number against every digit of the other and adds the shifted partial products. For an $n$-digit number times an $n$-digit number, that is $n^2$ single-digit multiplications, giving $\Theta(n^2)$ time. This is correct, simple, and exactly what most people learned on paper — it is also the baseline every faster algorithm in this lesson must beat.
multiply_naive(x, y): # x, y are n-digit non-negative integers
result = 0
for each digit y_i in y (with place value 10^i):
result += (x * y_i) * 10^i # one digit-by-number pass, shifted into place
return result
The obvious way to speed this up recursively is to split $x$ and $y$ in half and multiply the halves. That path is explored next — and it fails to improve on $\Theta(n^2)$ until one extra idea is added.
5. Karatsuba Multiplication
Split each $n$-digit number into a high half and a low half at the midpoint, so that $n/2$ digits sit above the split and $n/2$ below:
$$x = x_1 \cdot 10^{n/2} + x_0 \qquad y = y_1 \cdot 10^{n/2} + y_0$$
The product expands as $x \cdot y = x_1y_1 \cdot 10^{n} + (x_1y_0 + x_0y_1) \cdot 10^{n/2} + x_0y_0$. Read literally, that formula asks for four recursive sub-multiplications: $x_1y_1$, $x_1y_0$, $x_0y_1$, and $x_0y_0$. Recursing on that plan gives:
$$T(n) = 4T(n/2) + O(n)$$
which solves to $T(n) = O(n^2)$ — identical to naive multiplication. Splitting the number bought nothing, because the branching factor $a=4$ exactly cancels the size reduction $b=2$.
$$z_2 = x_1 y_1 \qquad z_0 = x_0 y_0 \qquad z_1 = (x_1+x_0)(y_1+y_0) - z_2 - z_0$$
Expanding $(x_1+x_0)(y_1+y_0) = x_1y_1 + x_1y_0 + x_0y_1 + x_0y_0 = z_2 + (x_1y_0+x_0y_1) + z_0$, so subtracting $z_2$ and $z_0$ isolates exactly $x_1y_0 + x_0y_1$ — the missing cross terms — without ever multiplying $x_1$ by $y_0$ or $x_0$ by $y_1$ directly. The final product reassembles from three sub-multiplications:
$$x \cdot y = z_2 \cdot 10^{n} + z_1 \cdot 10^{n/2} + z_0$$
Only $z_2$, $z_0$, and the product inside $z_1$ are recursive multiplications; everything else is addition, subtraction, and a fixed-position digit shift, all $O(n)$. The recurrence becomes:
$$T(n) = 3T(n/2) + O(n) = \Theta(n^{\log_2 3}) \approx O(n^{1.585})$$
This is exactly Example 3 of the Master Theorem walkthrough in the Recursion Complete Guide; that page derives the $n^{1.585}$ exponent from $a=3$, $b=2$, $f(n)=n$. This lesson will not repeat that derivation — the point here is that the exponent drops from 2 to 1.585 purely because $a$ dropped from 4 to 3.
flowchart TD
A["1234 x 5678 (n = 4 digits)"]
A -->|"z2 = high x high"| B["12 x 56 (n = 2 digits)"]
A -->|"z0 = low x low"| C["34 x 78 (n = 2 digits)"]
A -->|"z1 = sum x sum"| D["46 x 134 (n = 2 digits)"]
B -->|"z2"| B1["1 x 5 -> base case"]
B -->|"z0"| B2["2 x 6 -> base case"]
B -->|"z1"| B3["3 x 11 -> base case"]
C -.->|"same 3-way split"| C1["... -> base case"]
D -.->|"same 3-way split"| D1["... -> base case"]
Every node branches into exactly 3 children, never 4, and the digit count halves at each level ($n=4 \to n=2 \to n=1$), matching the recurrence $T(n)=3T(n/2)+O(n)$ derived above.
Each language panel below works directly on integers, splitting by digit count, and falls back to direct multiplication once a number is small enough that splitting no longer helps.
All three implementations were executed and cross-checked against direct multiplication (thousands of random inputs plus the fixed cases above); every result matched exactly.
Toom-Cook Multiplication
Karatsuba splits each number into 2 parts and turns 4 sub-multiplications into 3. Toom-Cook generalizes the same idea to splits of 3 or more parts. Splitting into 3 parts (Toom-3) naively needs $3 \times 3 = 9$ sub-multiplications; Toom-3 needs only 5.
The mechanism is different from Karatsuba's direct algebraic substitution, but the spirit is identical — do less multiplication work by being clever about what is computed. Treat each 3-part number as a degree-2 polynomial evaluated at the split base $b$: $p(t) = x_2t^2 + x_1t + x_0$ and $q(t) = y_2t^2+y_1t+y_0$, so that $x = p(b)$ and $y=q(b)$. Their product $r(t) = p(t)q(t)$ is a degree-4 polynomial with 5 unknown coefficients, and $x \cdot y = r(b)$. The algorithm has three phases:
- Evaluate: compute $p$ and $q$ at 5 chosen points (commonly $t = 0, 1, -1, 2, \infty$).
- Multiply pointwise: multiply the corresponding evaluations together — only 5 scalar products, each on smaller numbers.
- Interpolate: solve the resulting linear system for $r$'s 5 coefficients, then evaluate $r(b)$ (with carrying) to get $x \cdot y$.
The sketch below is conceptual rather than production-grade — it demonstrates the evaluate/multiply/interpolate structure on a single base-1000 split rather than a fully general arbitrary-precision Toom-3, but it is complete, runnable, and its output was verified against direct multiplication on hundreds of random inputs.
def toom3_sketch(x, y, base=1000):
"""Conceptual Toom-3: split into 3 limbs, evaluate at 5 points,
multiply pointwise (5 scalar products instead of 9), interpolate."""
m0, r = x % base, x // base
m1, m2 = r % base, r // base
n0, r = y % base, y // base
n1, n2 = r % base, r // base
def p(t): return m2 * t * t + m1 * t + m0
def q(t): return n2 * t * t + n1 * t + n0
# 1. Evaluate both polynomials at 5 points, including "infinity" (leading coeff)
r0, r1, rm1, r2, rinf = p(0) * q(0), p(1) * q(1), p(-1) * q(-1), p(2) * q(2), m2 * n2
# 2. The 5 pointwise products above are the only recursive multiplications
# 3. Interpolate the 5 coefficients c0..c4 of r(t) = c4*t^4 + ... + c0
c0, c4 = r0, rinf
s1, s2 = r1 - c0 - c4, rm1 - c0 - c4
s3 = r2 - c0 - 16 * c4
c2 = (s1 + s2) // 2
c3 = ((s3 - 4 * c2) // 2 - (s1 - s2) // 2) // 3
c1 = (s1 - s2) // 2 - c3
return c0 + c1 * base + c2 * base**2 + c3 * base**3 + c4 * base**4
print(toom3_sketch(123456, 789012)) # 97408265472
assert toom3_sketch(123456, 789012) == 123456 * 789012
For a $k$-way split, Toom-$k$ needs $2k-1$ sub-multiplications instead of the naive $k^2$, giving $T(n) = (2k-1)T(n/k) + O(n)$. As $k$ grows, the exponent $\log_k(2k-1)$ drifts toward 1, so Toom-Cook approaches (but never reaches) linear time — the general form is written $O(n^{1+\epsilon})$, with $\epsilon$ shrinking as the split count increases. In practice the interpolation constants grow quickly with $k$, so real libraries use only a few fixed variants (Toom-3, Toom-4, sometimes higher) before switching to FFT-based methods for truly huge inputs.
6. Strassen's Matrix Multiplication
Split each $n \times n$ matrix into four $n/2 \times n/2$ quadrants:
| $A = \begin{pmatrix}A_{11}&A_{12}\\A_{21}&A_{22}\end{pmatrix}$ | $B = \begin{pmatrix}B_{11}&B_{12}\\B_{21}&B_{22}\end{pmatrix}$ |
Block matrix multiplication follows the same rule as scalar multiplication, so the result's quadrants are $C_{11}=A_{11}B_{11}+A_{12}B_{21}$, $C_{12}=A_{11}B_{12}+A_{12}B_{22}$, $C_{21}=A_{21}B_{11}+A_{22}B_{21}$, $C_{22}=A_{21}B_{12}+A_{22}B_{22}$. Read literally, that is 8 recursive submatrix multiplications ($A_{11}B_{11}$, $A_{12}B_{21}$, $A_{11}B_{12}$, and so on), giving:
$$T(n) = 8T(n/2) + O(n^2)$$
which solves to $T(n) = O(n^3)$ — identical to standard triple-loop matrix multiplication. As with the naive number-splitting attempt above, block decomposition alone buys nothing.
$$M_1=(A_{11}+A_{22})(B_{11}+B_{22}) \quad M_2=(A_{21}+A_{22})B_{11} \quad M_3=A_{11}(B_{12}-B_{22})$$
$$M_4=A_{22}(B_{21}-B_{11}) \quad M_5=(A_{11}+A_{12})B_{22} \quad M_6=(A_{21}-A_{11})(B_{11}+B_{12}) \quad M_7=(A_{12}-A_{22})(B_{21}+B_{22})$$
Each $M_i$ is exactly one recursive submatrix multiplication (the sums and differences that build its operands are $O(n^2)$ additions, not multiplications). The four output quadrants recombine as:
$$C_{11}=M_1+M_4-M_5+M_7 \qquad C_{12}=M_3+M_5 \qquad C_{21}=M_2+M_4 \qquad C_{22}=M_1-M_2+M_3+M_6$$
Multiplying out $M_1$ through $M_7$ and substituting confirms these four combinations equal the four quadrant formulas from block multiplication above — the algebra is denser than Karatsuba's but the principle is the same substitution trick. With only 7 recursive multiplications:
$$T(n) = 7T(n/2) + O(n^2) = \Theta(n^{\log_2 7}) \approx O(n^{2.807})$$
This is exactly Example 4 of the Master Theorem walkthrough in the Recursion Complete Guide, which derives the $n^{2.807}$ exponent from $a=7$, $b=2$, $f(n)=n^2$. As with Karatsuba, the exponent drop (from 3 to 2.807) comes entirely from $a$ dropping from 8 to 7.
The implementation below assumes square, power-of-2-sized matrices for simplicity. Non-power-of-2 sizes require padding the matrix with zero rows and columns up to the next power of 2 before recursing, then discarding the padding from the result — a mechanical preprocessing step, described here in prose rather than implemented, since it adds no new algorithmic idea.
All three implementations were executed and cross-checked against naive matrix multiplication on random $2\times2$, $4\times4$, $8\times8$, and $16\times16$ integer matrices, plus the hand-traceable $2\times2$ case above; every result matched exactly.
Practical Crossover Points
Karatsuba and Strassen both trade multiplications for additions, and additions are only asymptotically free — at small sizes, the extra bookkeeping (recursive calls, allocating intermediate sums, combining results) costs more than the multiplications it avoids. Both algorithms need a crossover size below which the naive method is faster in practice, which is exactly why both implementations above include a base parameter that falls back to direct multiplication for small inputs.
- Karatsuba: commonly cited crossover points are in the range of a few hundred digits, depending on the platform and how well-optimized the base-case multiplication is. Below that, grade-school multiplication wins.
- Strassen: commonly cited crossover points are matrix dimensions in the low hundreds. Beyond the constant-factor overhead, Strassen's subtractions can amplify floating-point rounding error in ways naive triple-loop multiplication does not, so numerical-stability concerns make it less used in general-purpose numerical libraries than its asymptotic complexity alone would suggest.
- Recursion depth: both algorithms halve the input size at each level, so recursion depth is $O(\log n)$ for either one — a few dozen levels even for enormous inputs. Stack depth is essentially never the practical bottleneck; constant-factor overhead per call is.
Production libraries (arbitrary-precision arithmetic, BLAS-style linear algebra) typically implement exactly this pattern: naive method below a tuned threshold, Karatsuba/Strassen above it, and sometimes a third tier (Toom-Cook, or FFT-based multiplication) above an even larger threshold.
7. Complexity Comparison
| Algorithm | Recurrence | Time Complexity |
|---|---|---|
| Naive Multiplication | $T(n) = 4T(n/2) + O(n)$ | $O(n^2)$ |
| Karatsuba | $T(n) = 3T(n/2) + O(n)$ | $O(n^{1.585})$ |
| Toom-Cook ($k$-way) | $T(n) = (2k-1)T(n/k) + O(n)$ | $O(n^{1+\epsilon})$, $\epsilon \to 0$ as $k$ grows |
| Naive Matrix Multiply | $T(n) = 8T(n/2) + O(n^2)$ | $O(n^3)$ |
| Strassen | $T(n) = 7T(n/2) + O(n^2)$ | $O(n^{2.807})$ |
8. Applications & Alternatives
Where these algorithms show up
- Arbitrary-precision arithmetic libraries: GMP, Python's built-in big integers, and similar libraries switch to Karatsuba (and Toom-Cook) once operands exceed a tuned digit threshold.
- Cryptographic big-number operations: RSA key generation and modular exponentiation multiply numbers hundreds or thousands of bits long, well past Karatsuba's crossover point.
- Scientific computing matrix libraries: some dense linear algebra libraries apply Strassen-style block recursion for very large matrices, layered on top of highly tuned naive kernels for the base case.
- Contrast with sparse matrices: the Matrices: Special & Sparse lesson's Sparse Matrix Multiplication (LeetCode 311) uses a naive triple-loop approach tuned for sparsity, not Strassen's dense block recursion — the two techniques solve different problems and are not interchangeable.
Even faster algorithms exist asymptotically but are beyond this lesson's scope: the Schönhage–Strassen algorithm multiplies large integers via the Fast Fourier Transform in $O(n \log n \log\log n)$, and the Coppersmith–Winograd family of algorithms pushes matrix multiplication's exponent below Strassen's $2.807$ toward the theoretical lower bound of 2 — at the cost of galactic constant factors that make them impractical for any realistic input size.
9. Exercises
Easy
- Hand-trace Karatsuba on $34 \times 56$: compute $z_2$, $z_0$, and $z_1$, then combine them and verify against direct multiplication.
Medium
- Hand-trace Strassen's 7-product combination on $A=\begin{pmatrix}2&0\\1&3\end{pmatrix}$ and $B=\begin{pmatrix}1&4\\2&1\end{pmatrix}$ (treat each entry as a $1\times1$ block). Compute $M_1$ through $M_7$, combine into $C_{11}, C_{12}, C_{21}, C_{22}$, and verify against naive $2\times2$ matrix multiplication.
Hard
- The Karatsuba implementations above assume both numbers have roughly the same digit count. Design (do not necessarily implement) an extension that handles numbers of very different lengths, or an odd total digit count at the split point. Consider: does padding the shorter number with leading zeros to match a split point change the recurrence? What happens to the split when $n$ is odd — must $n/2$ round the same way for both halves?
Review rhythm: tomorrow, reconstruct the 3-product and 7-product formulas from scratch without notes; next week, implement both algorithms from memory in one language and test them against naive multiplication; several weeks later, recognize the same "shrink the branching factor" trick if it appears in an unfamiliar divide-and-conquer problem. Finally, teach someone who already knows the Master Theorem why $a$ dropping by one is enough to change the asymptotic complexity.
10. Summary Cheat Sheet
- Naive multiplication and naive matrix multiplication are both $\Theta(n^2)$ and $\Theta(n^3)$ respectively; splitting the input recursively without reducing the number of sub-products changes nothing.
- Karatsuba: 3 products instead of 4, $T(n)=3T(n/2)+O(n)=O(n^{1.585})$.
- Toom-$k$: $2k-1$ products instead of $k^2$, approaching $O(n^{1+\epsilon})$ as $k$ grows.
- Strassen: 7 products instead of 8, $T(n)=7T(n/2)+O(n^2)=O(n^{2.807})$.
- Both algorithms recover missing cross terms algebraically through addition/subtraction of a smaller set of products — the same trick, applied to numbers and to matrices.
- Both have significant constant-factor overhead; real crossover points are a few hundred digits (Karatsuba) or low hundreds of matrix dimension (Strassen), not the small examples used to teach the algorithm.
- Recursion depth is $O(\log n)$ for both — never the practical bottleneck.
- The Master Theorem examples for both recurrences already live in the Recursion Complete Guide; this lesson supplies the algorithms those examples only cited.