6.11.2.1 Polynomial Objects

class Polynomial
Polynomial base class.
Polynomial( parent, [is_gen=False])

The following examples illustrate creation of elements of polynomial rings, and some basic arithmetic.

First we make a polynomial over the integers and do some arithmetic:

sage: x = PolynomialRing(IntegerRing()).gen()
sage: f = x**5 + 2*x**2 + (-1); f
x^5 + 2*x^2 - 1
sage: f**2
x^10 + 4*x^7 - 2*x^5 + 4*x^4 - 4*x^2 + 1

Next we do arithmetic in a sparse polynomial ring over the integers:

sage: R = PolynomialRing(IntegerRing(), "x"); x = R.gen(); R
Univariate Polynomial Ring in x over Integer Ring
sage: S = PolynomialRing(R, "Z"); Z = S.gen(); S
Univariate Polynomial Ring in Z over Univariate Polynomial Ring in x over
Integer Ring
sage: f = Z**3 + (x**2-2*x+1)*Z - 3; f
Z^3 + (x^2 - 2*x + 1)*Z + -3
sage: f*f
Z^6 + (2*x^2 - 4*x + 2)*Z^4 + (-6)*Z^3 + (x^4 - 4*x^3 + 6*x^2 - 4*x +
1)*Z^2 + (-6*x^2 + 12*x - 6)*Z + 9
sage: f**3 == f*f*f
True

To have the element print as 'y', give 'y' as the second argument to the PolynomialRing constructor.

sage: y = PolynomialRing(IntegerRing(), 'y').gen()
sage: y**3 - 2*y
y^3 - 2*y

Instances of class Polynomial have the following methods (in addition to inherited methods and special methods):

base_ring,$  $ copy,$  $ degree,$  $ denominator,$  $ derivative,$  $ dict,$  $ factor,$  $ integral,$  $ inverse_of_unit,$  $ is_gen,$  $ is_irreducible,$  $ is_monic,$  $ is_unit,$  $ is_zero,$  $ leading_coefficient,$  $ list,$  $ make_monic,$  $ name,$  $ polynomial,$  $ resultant,$  $ reverse,$  $ roots,$  $ truncate,$  $ valuation

Further documentation:

base_ring( )

Return the base ring of the parent of self.

sage: x = PolynomialRing(ZZ).gen()
sage: x.base_ring()
Integer Ring
sage: (2*x+3).base_ring()
Integer Ring

copy( )

Return a copy of self.

We create the polynomial $ f=x+3$ , then set $ g=f$ , and change the coefficient of $ x$ in $ g$ , which also changes the coefficient of $ x$ in $ f$ . If we instead copy $ f$ , then changing the coefficient of $ x$ of $ g$ does not change $ f$ .

sage: x = PolynomialRing(IntegerRing()).gen()
sage: f = x+3
sage: g = f
sage: g[1]=3
sage: f
3*x + 3
sage: g = f.copy()
sage: g[1]=5
sage: f
3*x + 3
sage: g
5*x + 3

degree( )

Return the degree of this polynomial. The zero polynomial has degree -1.

sage: x = PolynomialRing(ZZ).gen()
sage: f = x**93 + 2*x + 1
sage: f.degree()
93
sage: x = PolynomialRing(QQ, sparse=True).gen()
sage: f = x**100000 
sage: f.degree()
100000

denominator( )

Return the least common multiple of the denominators of the entries of self, when this makes sense, i.e., when the coefficients have a denominator function.

WARNING: This is not the denominator of the rational function defined by self, which would always be 1 since self is a polynomial.

First we compute the denominator of a polynomial with integer coefficients, which is of course 1.

sage: x = PolynomialRing(IntegerRing()).gen()
sage: f = x**3 + 17*x + 1
sage: f.denominator()
1

Next we compute the denominator of a polynomial with rational coefficients.

sage: Q = RationalField()
sage: x = PolynomialRing(Q).gen()
sage: f = Q('1/17')*x**19 - Q('2/3')*x + Q('1/3'); f
1/17*x^19 - 2/3*x + 1/3
sage: f.denominator()
51

Finally, we try to compute the denominator of a polynomial with coefficients in the real numbers, which is a ring whose elements do not have a denominator method.

sage: R = RealField()
sage: x = PolynomialRing(R).gen()
sage: f = x + R('0.3'); f
1.0000000000000000*x + 0.29999999999999999
sage: f.denominator()
Traceback (most recent call last):
...
AttributeError: '_mpfr.RealNumber' object has no attribute 'denominator'

factor( )

Return polynomials f1, ..., fn and exponents e1, ..., en such that the gcd fo the coefficients of the fi is 1, and prod fi**ei is equal to a scalar multiple of self.

INPUT:
    a polynomial

OUTPUT:
    Factorization -- the factorization of self

sage: x = PolynomialRing(RationalField()).gen()
sage: f = (x**3 - 1)**2
sage: f.factor()
(x - 1)^2 * (x^2 + x + 1)^2

is_monic( )

Returns True if this polynomial is monic. The zero polynomial is by definition not monic.

make_monic( )

Return this polynomial divided by its leading coefficient.

roots( )

Return all roots of this polynomial.

sage: x = PolynomialRing(RationalField()).gen()
sage: f = x**3 - 1
sage: f.roots()
[(1, 1)]
sage: f = (x**3 - 1)**2
sage: f.roots()
[(1, 2)]

truncate( n)

Replace this polynomial by $ \sum a_m x^m$ where the sum is over $ m < n$ . The resulting polynomial is equivalent to self modulo $ x^n$ .

valuation( )

If $ f = a_r x^r + a_{r+1}x^{r+1} + \cdots$ , with $ a_r$ nonzero, then the valuation of $ f$ is $ r$ . The valuation of the zero polynomial is $ \infty$ .

Instances of class Polynomial also have the following special methods:

__call__,$  $ __cmp__,$  $ __float__,$  $ __floordiv__,$  $ __getitem__,$  $ __int__,$  $ __invert__,$  $ __long__,$  $ __mod__,$  $ __pow__,$  $ __repr__,$  $ __setitem__,$  $ _add,$  $ _factor_pari_helper,$  $ _integer_,$  $ _is_atomic,$  $ _latex_,$  $ _lcm,$  $ _mul,$  $ _mul_generic,$  $ _mul_karatsuba,$  $ _pari_,$  $ _xgcd

Further documentation:

__call__( a)

Evaluate polynomial at x=a using Horner's rule

INPUT:
    a -- ring element a; need not be in the coefficient
         ring of the polynomial.
OUTPUT:
    ring element, in the parent of a, if a is a ring element.

sage: x = PolynomialRing(QQ, 'x').gen()
sage: f = x - 5
sage: f(3)
-2
sage: f = (x-1)**5
sage: f(2)
1

AUTHOR: David Joyner, 2005-04-10.

__floordiv__( right)

Quotient of division of self by other. This is denoted //.

__mod__( other)

Remainder of division of self by other.

sage: x = PolynomialRing(IntegerRing()).gen()
sage: x % (x+1)
-1
sage: (x**3 + x - 1) % (x**2 - 1)
2*x - 1

_lcm( other)

Let f and g be two polynomials. Then this function returns the monic least common multiple of f and g.

_mul( right)

sage: x = PolynomialRing(IntegerRing()).gen()
sage: (x - 4)*(x**2 - 8*x + 16)
x^3 - 12*x^2 + 48*x - 64

_mul_karatsuba( right)

Returns the product of two polynomials using the Karatsuba divide and conquer multiplication algorithm. This is only used over a generic base ring. (Special libraries like NTL are used, e.g., for the integers and rationals, which are much faster.)

INPUT:
   self: Polynomial
   right: Polynomial (over same base ring as self)

OUTPUT: Polynomial
   The product self*right.

ALGORITHM: The basic idea is to use that

$\displaystyle (aX + b) (cX + d) = acX^2 + ((a+b)(c+d)-ac-bd)X + bd
$

where ac=a*c and bd=b*d, which requires three multiplications instead of the naive four. (In my examples, strangely just doing the above with four multiplications does tend to speed things up noticeably.) Given f and g of arbitrary degree bigger than one, let e be min(deg(f),deg(g))/2. Write

$\displaystyle f = a X^e + b$    and $\displaystyle g = c X^e + d
$

and use the identity

$\displaystyle (aX^e + b) (cX^e + d) = ac X^{2e} +((a+b)(c+d) - ac - bd)X^e + bd
$

to recursively compute $ fg$ .

TIMINGS: On a Pentium M 1.8Ghz laptop: f=R.random(1000,bound=100) g=R.random(1000,bound=100) time h=f._mul_karatsuba(g) Time: 0.42 seconds The naive multiplication algorithm takes 14.58 seconds. In contrast, MAGMA does this sort of product almost instantly, and can easily deal with degree 5000. Basically MAGMA is 100 times faster at polynomial multiplication.

Over Z using NTL, multiplying two polynomials constructed using R.random(10000,bound=100) takes 0.10 seconds. Using MAGMA V2.11-10 the same takes 0.14 seconds.

Over Q using PARI, multiplying two polynomials constructed using R.random(10000,bound=100) takes 1.23 seconds. Not good! TODO: use NTL polynomials over Z with a denominator instead of PARI.

NOTES: * Karatsuba multiplication of polynomials is also implemented in PARI in src/basemath/polarit3.c * The MAGMA documentation appears to give no information about how polynomial multiplication is implemented.

_xgcd( other)

Extended gcd of self and polynomial other.

See About this document... for information on suggesting changes.