Naive Approach

# input: A and B are the coefficients of two polynomials of degree m and n
# output: the (m+n-1) coefficients of the product of A and B
# time: O(m*n) (or O(n^2) if m=n)
# space: O(m+n)
def multiply(A, B, m, n): 
    prod = [0] * (m + n - 1); 
    for i in range(m): # A polynomial 
        for j in range(n): # B polynomial
            prod[i + j] += A[i] * B[j]; # Add A[i]*B[j] to the (i+j)th coefficient
    return prod; 

Karatsuba Algorithm for Polynomials

# input: p and q are the coefficients of two polynomials
# output: the coefficients of the product of p and q
# time: O(n^log2(3))
# space: O(n)
def karatsuba_poly_mult(p, q):
    # Base case: if either polynomial is empty, return an empty list
    if not p or not q:
        return []
 
    # Base case: if either polynomial is a constant, perform scalar multiplication
    if len(p) == 1:
        return [p[0] * qi for qi in q]
    if len(q) == 1:
        return [q[0] * pi for pi in p]
 
    # Determine the size for splitting the polynomials
    m = min(len(p), len(q)) // 2
 
    # Split the polynomials into lower and higher degree parts
    p_low = p[:m]
    p_high = p[m:]
    q_low = q[:m]
    q_high = q[m:]
 
    # Recursively compute the three products
    z0 = karatsuba_poly_mult(p_low, q_low)
    z2 = karatsuba_poly_mult(p_high, q_high)
    p_sum = [p_low[i] + p_high[i] for i in range(len(p_low))]
    q_sum = [q_low[i] + q_high[i] for i in range(len(q_low))]
    z1 = karatsuba_poly_mult(p_sum, q_sum)
 
    # Combine the results to get the final product
    result = [0] * (len(p) + len(q) - 1)
    for i in range(len(z0)):
        result[i] += z0[i]
    for i in range(len(z1)):
        result[i + m] += z1[i] - z0[i] - z2[i]
    for i in range(len(z2)):
        result[i + 2 * m] += z2[i]
 
    return result

Fast Polynomial Multiplication using FFT

Lagrange Polynomial

  • (Interpolation theorem) For every set of distinct points such that :
    • There is a unique polynomial of degree (at most) such that for all
      • is said to interpolate the set , and it is called the Lagrange interpolation polynomial of the set
    • (The points are called the interpolation points or data points, and are the interpolation nodes)
    • The Lagrange interpolation polynomial can be computed in time

Naive Algorithm for Polynomial Mul. u/ Lagrange Interpolation

  • Algorithm:
    • Input: Two polynomials and of degree at most
    • Let be the smallest power of such that
    • Choose distinct points in
    • Find the Lagrange interpolation polynomial of the set

In this approach, the multiplication operation () is easily performed in linear time, but the interpolation step is done in time, which of course is not efficient compared to the previous approaches. However, we will see that by selecting the points carefully, we can achieve a more efficient divide-and-conquer algorithm that is efficient for both evaluation and interpolation steps. The smart choice of points will be in the complex plane, so the algorithm will be for polynomials in

Polynomial Multiplication u/ FFT

  • Input:
    • Two polynomials with degree less than for some integer
    • A primitive th root of unity
  • (Calculate the DFT of and using FFT)
    • is an th primitive root of unity,
  • (Pointwise multiplication)
  • (Calculate the IDFT of using FFT)