# Revision history [back]

For integer polynomials, FLINT is used to do the multiplication. We look at the _mul_ method since in Sage, __mul__ is used to handle coercion and then dispatches to _mul_.

sage: R.<x> = ZZ[]
sage: x._mul_??
...
cpdef RingElement _mul_(self, RingElement right):
r"""
Returns self multiplied by right.

EXAMPLES::

sage: R.<x> = PolynomialRing(ZZ)
sage: (x - 2)*(x^2 - 8*x + 16)
x^3 - 10*x^2 + 32*x - 32
"""
cdef Polynomial_integer_dense_flint x = self._new()
sig_on()
fmpz_poly_mul(x.__poly, self.__poly,
(<Polynomial_integer_dense_flint>right).__poly)
sig_off()
return x


You can do a similar check to see that FLINT's fmpq_poly_mul is used for polynomials over the rationals.

The univariate polynomials over finite fields different based on the size of the field. For example, for small primes, FLINT is used:

sage: R.<x> = GF(next_prime(2^5))[]
sage: type(x)
<type 'sage.rings.polynomial.polynomial_zmod_flint.Polynomial_zmod_flint'>


But for larger primes, NTL is used:

sage: R.<x> = GF(next_prime(2^64))[]
sage: type(x)
<type 'sage.rings.polynomial.polynomial_modn_dense_ntl.Polynomial_dense_mod_p'>


To find out the exact algorithm / heuristics used, you'll need to delve into those packages.