Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Elements of Laurent polynomial rings """
#***************************************************************************** # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import print_function
from sage.rings.integer cimport Integer from sage.structure.element import is_Element, coerce_binop from sage.misc.misc import union from sage.structure.factorization import Factorization from sage.misc.derivative import multi_derivative from sage.rings.polynomial.polynomial_element import Polynomial from sage.structure.richcmp cimport richcmp, rich_to_bool
cdef class LaurentPolynomial(CommutativeAlgebraElement): """ Base class for Laurent polynomials. """ cpdef _add_(self, other): """ Abstract addition method
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(ZZ) sage: from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial sage: LaurentPolynomial._add_(x, x) Traceback (most recent call last): ... NotImplementedError """
cpdef _mul_(self, other): """ Abstract multiplication method
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(ZZ) sage: from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial sage: LaurentPolynomial._mul_(x, x) Traceback (most recent call last): ... NotImplementedError """
cpdef _floordiv_(self, other): """ Abstract floor division method
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(ZZ) sage: from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial sage: LaurentPolynomial._floordiv_(x, x) Traceback (most recent call last): ... NotImplementedError """
def _integer_(self, ZZ): r""" Convert this Laurent polynomial to an integer.
This is only possible if the Laurent polynomial is constant.
OUTPUT:
An integer.
TESTS::
sage: L.<a> = LaurentPolynomialRing(QQ) sage: L(42)._integer_(ZZ) 42 sage: a._integer_(ZZ) Traceback (most recent call last): ... ValueError: a is not constant sage: L(2/3)._integer_(ZZ) Traceback (most recent call last): ... TypeError: no conversion of this rational to integer sage: ZZ(L(42)) 42
::
sage: L.<a, b> = LaurentPolynomialRing(QQ) sage: L(42)._integer_(ZZ) 42 sage: a._integer_(ZZ) Traceback (most recent call last): ... ValueError: a is not constant sage: L(2/3)._integer_(ZZ) Traceback (most recent call last): ... TypeError: no conversion of this rational to integer sage: ZZ(L(42)) 42 """
def _rational_(self): r""" Convert this Laurent polynomial to a rational.
This is only possible if the Laurent polynomial is constant.
OUTPUT:
A rational.
TESTS::
sage: L.<a> = LaurentPolynomialRing(QQ) sage: L(42)._rational_() 42 sage: a._rational_() Traceback (most recent call last): ... ValueError: a is not constant sage: QQ(L(2/3)) 2/3
::
sage: L.<a, b> = LaurentPolynomialRing(QQ) sage: L(42)._rational_() 42 sage: a._rational_() Traceback (most recent call last): ... ValueError: a is not constant sage: QQ(L(2/3)) 2/3 """
def change_ring(self, R): """ Return a copy of this Laurent polynomial, with coefficients in ``R``.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: a = x^2 + 3*x^3 + 5*x^-1 sage: a.change_ring(GF(3)) 2*x^-1 + x^2
Check that :trac:`22277` is fixed::
sage: R.<x, y> = LaurentPolynomialRing(QQ) sage: a = 2*x^2 + 3*x^3 + 4*x^-1 sage: a.change_ring(GF(3)) -x^2 + x^-1 """
cpdef long number_of_terms(self) except -1: """ Abstract method for number of terms
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(ZZ) sage: from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial sage: LaurentPolynomial.number_of_terms(x) Traceback (most recent call last): ... NotImplementedError """
def hamming_weight(self): """ Return the number of non-zero coefficients of self. Also called weight, hamming weight or sparsity.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(ZZ) sage: f = x^3 - 1 sage: f.number_of_terms() 2 """
cdef class LaurentPolynomial_univariate(LaurentPolynomial): """ A univariate Laurent polynomial in the form of `t^n \cdot f` where `f` is a polynomial in `t`.
INPUT:
- ``parent`` -- a Laurent polynomial ring
- ``f`` -- a polynomial (or something can be coerced to one)
- ``n`` -- (default: 0) an integer
AUTHORS:
- Tom Boothby (2011) copied this class almost verbatim from ``laurent_series_ring_element.pyx``, so most of the credit goes to William Stein, David Joyner, and Robert Bradshaw - Travis Scrimshaw (09-2013): Cleaned-up and added a few extra methods """ def __init__(self, parent, f, n=0): r""" Create the Laurent polynomial `t^n \cdot f`.
EXAMPLES::
sage: R.<q> = LaurentPolynomialRing(ZZ) sage: R([1,2,3]) 1 + 2*q + 3*q^2 sage: TestSuite(q^-3 + 3*q + 2).run()
::
sage: S.<s> = LaurentPolynomialRing(GF(5)) sage: T.<t> = PolynomialRing(pAdicRing(5)) sage: S(t) s sage: parent(S(t)) Univariate Laurent Polynomial Ring in s over Finite Field of size 5 sage: parent(S(t)[1]) Finite Field of size 5
::
sage: R({}) 0 """
n += (<LaurentPolynomial_univariate>f).__n if (<LaurentPolynomial_univariate>f).__u._parent is parent.polynomial_ring(): f = (<LaurentPolynomial_univariate>f).__u else: f = parent.polynomial_ring()((<LaurentPolynomial_univariate>f).__u)
# self is that t^n * u:
def __reduce__(self): """ Used in pickling.
EXAMPLES::
sage: R.<q> = LaurentPolynomialRing(ZZ) sage: elt = q^-3 + 2 + q sage: loads(dumps(elt)) == elt True """
def is_unit(self): """ Return ``True`` if this Laurent polynomial is a unit in this ring.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: (2+t).is_unit() False sage: f = 2*t sage: f.is_unit() True sage: 1/f 1/2*t^-1 sage: R(0).is_unit() False sage: R.<s> = LaurentPolynomialRing(ZZ) sage: g = 2*s sage: g.is_unit() False sage: 1/g 1/2*s^-1
ALGORITHM: A Laurent polynomial is a unit if and only if its "unit part" is a unit. """
def is_zero(self): """ Return ``1`` if ``self`` is 0, else return ``0``.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: f = 1/x + x + x^2 + 3*x^4 sage: f.is_zero() 0 sage: z = 0*f sage: z.is_zero() 1 """
def __nonzero__(self): """ Check if ``self`` is non-zero.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: f = 1/x + x + x^2 + 3*x^4 sage: not f False sage: z = 0*f sage: not z True """
def _im_gens_(self, codomain, im_gens): """ Return the image of ``self`` under the morphism defined by ``im_gens`` in ``codomain``.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: H = Hom(R, QQ) sage: mor = H(2) sage: mor(t^2 + t^-2) 17/4 sage: 4 + 1/4 17/4 """
def __normalize(self): r""" A Laurent series is a pair `(u(t), n)`, where either `u = 0` (to some precision) or `u` is a unit. This pair corresponds to `t^n \cdot u(t)`.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: elt = t^2 + t^4 # indirect doctest sage: elt.polynomial_construction() (t^2 + 1, 2)
Check that :trac:`21272` is fixed::
sage: (t - t).polynomial_construction() (0, 0) """ # we already caught the infinity and zero cases
def _repr_(self): """ Return a string representation of ``self``.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: 2 + (2/3)*t^3 2 + 2/3*t^3 """ else:
def _latex_(self): r""" EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: f = (17/2)*x^-2 + x + x^2 + 3*x^4 sage: latex(f) \frac{\frac{17}{2}}{x^{2}} + x + x^{2} + 3x^{4}
Verify that :trac:`6656` has been fixed::
sage: R.<a,b>=PolynomialRing(QQ) sage: T.<x>=LaurentPolynomialRing(R) sage: y = a*x+b*x sage: y._latex_() '\\left(a + b\\right)x' sage: latex(y) \left(a + b\right)x
TESTS::
sage: L.<lambda2> = LaurentPolynomialRing(QQ) sage: latex(L.an_element()) \lambda_{2} sage: L.<y2> = LaurentPolynomialRing(QQ) sage: latex(L.an_element()) y_{2} """
return "0" else: # negative e s += "\\frac{{{}}}{{{}}}".format(x, X) else:
def __hash__(self): """ Return the hash of ``self``.
TESTS::
sage: R = LaurentPolynomialRing(QQ, 't')
sage: assert hash(R.zero()) == 0 sage: assert hash(R.one()) == 1 sage: assert hash(QQ['t'].gen()) == hash(R.gen())
sage: for _ in range(20): ....: p = QQ.random_element() ....: assert hash(R(p)) == hash(p), "p = {}".format(p)
sage: S.<t> = QQ[] sage: for _ in range(20): ....: p = S.random_element() ....: assert hash(R(p)) == hash(p), "p = {}".format(p) ....: assert hash(R(t*p)) == hash(t*p), "p = {}".format(p)
Check that :trac:`21272` is fixed::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: hash(R.zero()) == hash(t - t) True """
# we reimplement below the hash of polynomials to handle negative # degrees cdef long result_mon cdef int i,j
def __getitem__(self, i): """ Return the `i`-th coefficient of ``self``.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: f = -5/t^(10) + t + t^2 - 10/3*t^3; f -5*t^-10 + t + t^2 - 10/3*t^3 sage: f[-10] -5 sage: f[1] 1 sage: f[3] -10/3 sage: f[-9] 0 sage: f = -5/t^(10) + 1/3 + t + t^2 - 10/3*t^3; f -5*t^-10 + 1/3 + t + t^2 - 10/3*t^3
Slicing is deprecated::
sage: f[-10:2] doctest:...: DeprecationWarning: polynomial slicing with a start index is deprecated, use list() and slice the resulting list instead See http://trac.sagemath.org/18940 for details. -5*t^-10 + 1/3 + t sage: f[0:] 1/3 + t + t^2 - 10/3*t^3 sage: f[:3] -5*t^-10 + 1/3 + t + t^2 sage: f[-14:5:2] Traceback (most recent call last): ... NotImplementedError: polynomial slicing with a step is not defined """
cpdef long number_of_terms(self) except -1: """ Return the number of non-zero coefficients of self. Also called weight, hamming weight or sparsity.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(ZZ) sage: f = x^3 - 1 sage: f.number_of_terms() 2 sage: R(0).number_of_terms() 0 sage: f = (x+1)^100 sage: f.number_of_terms() 101
The method :meth:`hamming_weight` is an alias::
sage: f.hamming_weight() 101 """
def __iter__(self): """ Iterate through the coefficients from the first nonzero one to the last nonzero one.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: f = -5/t^(2) + t + t^2 - 10/3*t^3; f -5*t^-2 + t + t^2 - 10/3*t^3 sage: for a in f: print(a) -5 0 0 1 1 -10/3 """
def _symbolic_(self, R): """ EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: f = x^3 + 2/x sage: g = f._symbolic_(SR); g (x^4 + 2)/x sage: g(x=2) 9
sage: g = SR(f) sage: g(x=2) 9
Since :trac:`24072` the symbolic ring does not accept positive characteristic::
sage: R.<w> = LaurentPolynomialRing(GF(7)) sage: SR(2*w^3 + 1) Traceback (most recent call last): ... TypeError: positive characteristic not allowed in symbolic computations """
def dict(self): """ Return a dictionary representing ``self``.
EXAMPLES:: sage: R.<x,y> = ZZ[] sage: Q.<t> = LaurentPolynomialRing(R) sage: f = (x^3 + y/t^3)^3 + t^2; f y^3*t^-9 + 3*x^3*y^2*t^-6 + 3*x^6*y*t^-3 + x^9 + t^2 sage: f.dict() {-9: y^3, -6: 3*x^3*y^2, -3: 3*x^6*y, 0: x^9, 2: 1} """
def coefficients(self): """ Return the nonzero coefficients of ``self``.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: f = -5/t^(2) + t + t^2 - 10/3*t^3 sage: f.coefficients() [-5, 1, 1, -10/3] """
def exponents(self): """ Return the exponents appearing in ``self`` with nonzero coefficients.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: f = -5/t^(2) + t + t^2 - 10/3*t^3 sage: f.exponents() [-2, 1, 2, 3] """
def __setitem__(self, n, value): """ EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: f = t^2 + t^-3 sage: f[2] = 5 Traceback (most recent call last): ... IndexError: Laurent polynomials are immutable """
def _unsafe_mutate(self, i, value): """ Sage assumes throughout that commutative ring elements are immutable. This is relevant for caching, etc. But sometimes you need to change a Laurent polynomial and you really know what you're doing. That's when this function is for you.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: f = t^2 + t^-3 sage: f._unsafe_mutate(2, 3) sage: f t^-3 + 3*t^2 """ else: # off to the left if value != 0: self.__n = self.__n + j R = self._parent.base_ring() coeffs = [value] + [R(0) for _ in range(1,-j)] + self.__u.list() self.__u = self.__u._parent(coeffs)
cpdef _add_(self, right_m): """ Add two Laurent polynomials with the same parent.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: t + t 2*t sage: f = 1/t + t^2 + t^3 - 17/3 * t^4 sage: g = 2/t + t^3 sage: f + g 3*t^-1 + t^2 + 2*t^3 - 17/3*t^4 sage: f + 0 t^-1 + t^2 + t^3 - 17/3*t^4 sage: 0 + f t^-1 + t^2 + t^3 - 17/3*t^4 sage: R(0) + R(0) 0 sage: t^3 + t^-3 t^-3 + t^3
ALGORITHM: Shift the unit parts to align them, then add. """ cdef long m
# 1. Special case when one or the other is 0.
# 2. Align the unit parts. else: # 3. Add
cpdef _sub_(self, right_m): """ Subtract two Laurent polynomials with the same parent.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: t - t 0 sage: t^5 + 2 * t^-5 2*t^-5 + t^5
ALGORITHM: Shift the unit parts to align them, then subtract. """ cdef long m
# 1. Special case when one or the other is 0.
# 2. Align the unit parts. else: # 3. Subtract
def degree(self): """ Return the degree of this polynomial.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(ZZ) sage: g = x^2 - x^4 sage: g.degree() 4 sage: g = -10/x^5 + x^2 - x^7 sage: g.degree() 7 """
def __neg__(self): """ Return the negative of ``self``.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(ZZ) sage: -(1+t^5) -1 - t^5 """
cpdef _mul_(self, right_r): """ EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(GF(2)) sage: f = 1/x^3 + x + x^2 + 3*x^4 sage: g = 1 - x + x^2 - x^4 sage: f*g x^-3 + x^-2 + x^-1 + x^8 """
cpdef _rmul_(self, Element c): """ EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(ZZ) sage: f = 1/x^3 + x + x^2 + 3*x^4 sage: 3 * f 3*x^-3 + 3*x + 3*x^2 + 9*x^4 """
cpdef _lmul_(self, Element c): """ EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(ZZ) sage: f = 1/x^3 + x + x^2 + 3*x^4 sage: f * 3 3*x^-3 + 3*x + 3*x^2 + 9*x^4 """
def is_monomial(self): """ Return True if this element is a monomial. That is, if self is `x^n` for some integer `n`.
EXAMPLES::
sage: k.<z> = LaurentPolynomialRing(QQ) sage: z.is_monomial() True sage: k(1).is_monomial() True sage: (z+1).is_monomial() False sage: (z^-2909).is_monomial() True sage: (38*z^-2909).is_monomial() False """
def __pow__(_self, r, dummy): """ EXAMPLES::
sage: x = LaurentPolynomialRing(QQ,'x').0 sage: f = x + x^2 + 3*x^4 sage: g = 1/x^10 - x sage: f^3 x^3 + 3*x^4 + 3*x^5 + 10*x^6 + 18*x^7 + 9*x^8 + 27*x^9 + 27*x^10 + 27*x^12 sage: g^4 x^-40 - 4*x^-29 + 6*x^-18 - 4*x^-7 + x^4 """ raise ValueError("exponent must be an integer")
cpdef _floordiv_(self, rhs): """ Perform division with remainder and return the quotient.
EXAMPLES::
sage: L.<x> = LaurentPolynomialRing(QQ) sage: f = x^3 + x^-3 sage: g = x^-1 + x sage: f // g x^-2 - 1 + x^2 sage: g * (f // g) == f True sage: f // 1 x^-3 + x^3 sage: 1 // f 0 """
def shift(self, k): r""" Return this Laurent polynomial multiplied by the power `t^n`. Does not change this polynomial.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ['y']) sage: f = (t+t^-1)^4; f t^-4 + 4*t^-2 + 6 + 4*t^2 + t^4 sage: f.shift(10) t^6 + 4*t^8 + 6*t^10 + 4*t^12 + t^14 sage: f >> 10 t^-14 + 4*t^-12 + 6*t^-10 + 4*t^-8 + t^-6 sage: f << 4 1 + 4*t^2 + 6*t^4 + 4*t^6 + t^8 """
def __lshift__(LaurentPolynomial_univariate self, k): """ Return the left shift of ``self``.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: f = (t+t^-1)^4; f t^-4 + 4*t^-2 + 6 + 4*t^2 + t^4 sage: f << 4 1 + 4*t^2 + 6*t^4 + 4*t^6 + t^8 """
def __rshift__(LaurentPolynomial_univariate self, k): """ Return the right shift of ``self``.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: f = (t+t^-1)^4; f t^-4 + 4*t^-2 + 6 + 4*t^2 + t^4 sage: f >> 10 t^-14 + 4*t^-12 + 6*t^-10 + 4*t^-8 + t^-6 """
cpdef _div_(self, rhs): """ EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: f = x + x^2 + 3*x^4 sage: g = 1/x^7 - x + x^2 - x^4 sage: f / x 1 + x + 3*x^3 sage: f / g (3*x^11 + x^9 + x^8)/(-x^11 + x^9 - x^8 + 1) sage: (x^-2 + x)*(x^-2 + 1) / ((x^5 + x^8)*(x + 2)) (x^2 + 1)/(x^10 + 2*x^9) sage: (x^-2 + x)*(x^-2 + 1) / ((x^-5 + x^-8)*(x + 2)) (x^6 + x^4)/(x + 2) """ raise ZeroDivisionError
def __invert__(self): """ Return the inverse of ``self``.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: i = ~(t^-2); i t^2 sage: i.parent() is R True sage: i = ~(2*t^2); i 1/2*t^-2 sage: i.parent() is R True sage: i = ~(t^-2 + 2 + t^2); i t^2/(t^4 + 2*t^2 + 1) sage: i.parent() Fraction Field of Univariate Polynomial Ring in t over Rational Field """ # Enlarge the ring so we can divide by the coefficient
def inverse_of_unit(self): """ Return the inverse of ``self`` if a unit.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: (t^-2).inverse_of_unit() t^2 sage: (t + 2).inverse_of_unit() Traceback (most recent call last): ... ArithmeticError: element is not a unit """
def _fraction_pair(self): """ Return one representation of ``self`` as a pair ``(numerator, denominator)``.
Here both the numerator and the denominator are polynomials.
This is used for coercion into the fraction field.
EXAMPLES::
sage: L.<x> = LaurentPolynomialRing(QQ) sage: f = 4*x^-7 + 3*x^3 + 1 + 2*x^4 + x^6 sage: f._fraction_pair() (x^13 + 2*x^11 + 3*x^10 + x^7 + 4, x^7) """
def gcd(self, right): """ Return the gcd of ``self`` with ``right`` where the common divisor ``d`` makes both ``self`` and ``right`` into polynomials with the lowest possible degree.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: t.gcd(2) 1 sage: gcd(t^-2 + 1, t^-4 + 3*t^-1) t^-4 sage: gcd((t^-2 + t)*(t + t^-1), (t^5 + t^8)*(1 + t^-2)) t^-3 + t^-1 + 1 + t^2 """
@coerce_binop def quo_rem(self, right_r): """ Attempts to divide ``self`` by ``right`` and returns a quotient and a remainder.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: (t^-3 - t^3).quo_rem(t^-1 - t) (t^-2 + 1 + t^2, 0) sage: (t^-2 + 3 + t).quo_rem(t^-4) (t^2 + 3*t^4 + t^5, 0) sage: (t^-2 + 3 + t).quo_rem(t^-4 + t) (0, 1 + 3*t^2 + t^3) """
cpdef _richcmp_(self, right_r, int op): r""" Comparison of ``self`` and ``right_r``.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: f = x^(-1) + 1 + x sage: g = x^(-1) + 1 sage: f == g False
::
sage: f = x^(-1) + 1 + x sage: g = x^(-1) + 2 sage: f == g False sage: f != g True sage: f < g True sage: f <= g True sage: f > g False sage: f >= g False
::
sage: f = x^(-2) + 1 + x sage: g = x^(-1) + 2 sage: f == g False sage: f < g False sage: f > g True """
# zero pad coefficients on the left, to line them up for comparison
# zero pad on right to make the lists the same length # (this is necessary since the power series list() function just # returns the coefficients of the underlying polynomial, which may # have zeroes in the high coefficients)
def valuation(self, p=None): """ Return the valuation of ``self``.
The valuation of a Laurent polynomial `t^n u` is `n` plus the valuation of `u`.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(ZZ) sage: f = 1/x + x^2 + 3*x^4 sage: g = 1 - x + x^2 - x^4 sage: f.valuation() -1 sage: g.valuation() 0 """
def truncate(self, n): """ Return a polynomial with degree at most `n-1` whose `j`-th coefficients agree with ``self`` for all `j < n`.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: f = 1/x^12 + x^3 + x^5 + x^9 sage: f.truncate(10) x^-12 + x^3 + x^5 + x^9 sage: f.truncate(5) x^-12 + x^3 sage: f.truncate(-16) 0 """
def variable_name(self): """ Return the name of variable of ``self`` as a string.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: f = 1/x + x^2 + 3*x^4 sage: f.variable_name() 'x' """
def variables(self): """ Return the tuple of variables occuring in this Laurent polynomial.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: f = 1/x + x^2 + 3*x^4 sage: f.variables() (x,) sage: R.one().variables() () """
def polynomial_construction(self): """ Return the polynomial and the shift in power used to construct the Laurent polynomial `t^n u`.
OUTPUT:
A tuple ``(u, n)`` where ``u`` is the underlying polynomial and ``n`` is the power of the exponent shift.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: f = 1/x + x^2 + 3*x^4 sage: f.polynomial_construction() (3*x^5 + x^3 + 1, -1) """
def is_constant(self): """ Return whether this Laurent polynomial is constant.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: x.is_constant() False sage: R.one().is_constant() True sage: (x^-2).is_constant() False sage: (x^2).is_constant() False sage: (x^-2 + 2).is_constant() False sage: R(0).is_constant() True sage: R(42).is_constant() True sage: x.is_constant() False sage: (1/x).is_constant() False """
def __copy__(self): """ Return a copy of ``self``.
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: f = 1/x + x^2 + 3*x^4 sage: cf = copy(f) sage: cf == f True sage: cf is not f True """
def derivative(self, *args): """ The formal derivative of this Laurent polynomial, with respect to variables supplied in args.
Multiple variables and iteration counts may be supplied. See documentation for the global :func:`derivative` function for more details.
.. SEEALSO::
:meth:`_derivative`
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(QQ) sage: g = 1/x^10 - x + x^2 - x^4 sage: g.derivative() -10*x^-11 - 1 + 2*x - 4*x^3 sage: g.derivative(x) -10*x^-11 - 1 + 2*x - 4*x^3
::
sage: R.<t> = PolynomialRing(ZZ) sage: S.<x> = LaurentPolynomialRing(R) sage: f = 2*t/x + (3*t^2 + 6*t)*x sage: f.derivative() -2*t*x^-2 + (3*t^2 + 6*t) sage: f.derivative(x) -2*t*x^-2 + (3*t^2 + 6*t) sage: f.derivative(t) 2*x^-1 + (6*t + 6)*x """
def _derivative(self, var=None): """ The formal derivative of this Laurent series with respect to ``var``.
If ``var`` is ``None`` or the generator of this ring, it's the formal derivative as expected. Otherwise, ``_derivative(var)`` gets called recursively on each coefficient.
.. SEEALSO::
:meth:`derivative`
EXAMPLES::
sage: R.<x> = LaurentPolynomialRing(ZZ) sage: f = x^2 + 3*x^4 sage: f._derivative() 2*x + 12*x^3 sage: f._derivative(x) 2*x + 12*x^3 sage: g = 1/x^10 - x + x^2 - x^4 sage: g._derivative() -10*x^-11 - 1 + 2*x - 4*x^3
Differentiating with respect to something other than the generator gets recursed into the base ring::
sage: R.<t> = PolynomialRing(ZZ) sage: S.<x> = LaurentPolynomialRing(R) sage: f = 2*t/x + (3*t^2 + 6*t)*x sage: f._derivative(t) 2*x^-1 + (6*t + 6)*x """ # call _derivative() recursively on coefficients
# compute formal derivative with respect to generator return LaurentPolynomial_univariate(self._parent, 0)
def integral(self): r""" The formal integral of this Laurent series with 0 constant term.
EXAMPLES:
The integral may or may not be defined if the base ring is not a field.
::
sage: t = LaurentPolynomialRing(ZZ, 't').0 sage: f = 2*t^-3 + 3*t^2 sage: f.integral() -t^-2 + t^3
::
sage: f = t^3 sage: f.integral() Traceback (most recent call last): ... ArithmeticError: coefficients of integral cannot be coerced into the base ring
The integral of `1/t` is `\log(t)`, which is not given by a Laurent polynomial::
sage: t = LaurentPolynomialRing(ZZ,'t').0 sage: f = -1/t^3 - 31/t sage: f.integral() Traceback (most recent call last): ... ArithmeticError: the integral of is not a Laurent polynomial, since t^-1 has nonzero coefficient
Another example with just one negative coefficient::
sage: A.<t> = LaurentPolynomialRing(QQ) sage: f = -2*t^(-4) sage: f.integral() 2/3*t^-3 sage: f.integral().derivative() == f True """ "the integral of is not a Laurent polynomial, since t^-1 has nonzero coefficient")
else:
def __call__(self, *x, **kwds): """ Compute value of this Laurent polynomial at ``x``.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(ZZ) sage: f = t^(-2) + t^2 sage: f(2) 17/4 sage: f(-1) 2 sage: f(1/3) 82/9 sage: f(t=-1) 2 sage: f(x=-1) t^-2 + t^2 sage: f() t^-2 + t^2 sage: f(1,2) Traceback (most recent call last): ... TypeError: number of arguments does not match number of variables in parent """ return f(*x) else:
" of variables in parent")
def factor(self): """ Return a Laurent monomial (the unit part of the factorization) and a factored polynomial.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(ZZ) sage: f = 4*t^-7 + 3*t^3 + 2*t^4 + t^-6 sage: f.factor() (t^-7) * (4 + t + 3*t^10 + 2*t^11) """
u *= d ** t[1] else:
def residue(self): """ Return the residue of ``self``.
The residue is the coefficient of `t^-1`.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: f = 3*t^-2 - t^-1 + 3 + t^2 sage: f.residue() -1 sage: g = -2*t^-2 + 4 + 3*t sage: g.residue() 0 sage: f.residue().parent() Rational Field """
def constant_coefficient(self): """ Return the coefficient of the constant term of ``self``.
EXAMPLES::
sage: R.<t> = LaurentPolynomialRing(QQ) sage: f = 3*t^-2 - t^-1 + 3 + t^2 sage: f.constant_coefficient() 3 sage: g = -2*t^-2 + t^-1 + 3*t sage: g.constant_coefficient() 0 """
cdef class LaurentPolynomial_mpair(LaurentPolynomial): """ Multivariate Laurent polynomials. """ def __init__(self, parent, x, mon=None, reduce=True): """ Currently, one can only create LaurentPolynomials out of dictionaries and elements of the base ring.
INPUT:
- ``parent`` -- a SageMath parent
- ``x`` -- an element or dictionary or anything the underlying polynomial ring accepts
- ``mon`` -- (default: ``None``) a tuple specifying the shift in the exponents
- ``reduce`` -- (default: ``True``) a boolean
EXAMPLES::
sage: L.<w,z> = LaurentPolynomialRing(QQ) sage: f = L({(-1,-1):1}); f w^-1*z^-1 sage: f = L({(1,1):1}); f w*z sage: f = L({(-1,-1):1, (1,3):4}); f 4*w*z^3 + w^-1*z^-1 sage: L(1/2) 1/2
TESTS:
Check that :trac:`19538` is fixed::
sage: R = LaurentPolynomialRing(QQ,'x2,x0') sage: S = LaurentPolynomialRing(QQ,'x',3) sage: f = S.coerce_map_from(R) sage: f(R.gen(0) + R.gen(1)^2) x0^2 + x2 sage: _.parent() Multivariate Laurent Polynomial Ring in x0, x1, x2 over Rational Field
::
sage: from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial_mpair sage: LaurentPolynomial_mpair(L, {(1,2): 1/42}, mon=(-3, -3)) 1/42*w^-2*z^-1
:trac:`22398`::
sage: LQ = LaurentPolynomialRing(QQ, 'x0, x1, x2, y0, y1, y2, y3, y4, y5') sage: LZ = LaurentPolynomialRing(ZZ, 'x0, x1, x2, y0, y1, y2, y3, y4, y5') sage: LQ.inject_variables() Defining x0, x1, x2, y0, y1, y2, y3, y4, y5 sage: x2^-1*y0*y1*y2*y3*y4*y5 + x1^-1*x2^-1*y0*y1*y3*y4 + x0^-1 in LZ True sage: x2^-1*y0*y1*y2*y3*y4*y5 + x1^-1*x2^-1*y0*y1*y3*y4 + x0^-1*x1^-1*y0*y3 + x0^-1 in LZ True
Check that input is not modified::
sage: LQ.<x,y> = LaurentPolynomialRing(QQ) sage: D = {(-1, 1): 1} sage: k = tuple(D)[0] sage: v = D[k] sage: type(k), type(v) (<... 'tuple'>, <type 'sage.rings.integer.Integer'>) sage: LQ(D) x^-1*y sage: tuple(D)[0] is k True sage: D[k] is v True """ else: else: self._mon = ETuple({}, int(parent.ngens())) break else: else: # since x should coerce into parent, _mon should be (0,...,0)
def __reduce__(self): """ TESTS::
sage: R = LaurentPolynomialRing(QQ,2,'x') sage: R.<x1,x2> = LaurentPolynomialRing(QQ) sage: loads(dumps(x1)) == x1 # indirect doctest True sage: z = x1/x2 sage: loads(dumps(z)) == z True """
def __hash__(self): r""" TESTS:
Test that the hash is non-constant::
sage: L.<w,z> = LaurentPolynomialRing(QQ) sage: len({hash(w^i*z^j) for i in [-2..2] for j in [-2..2]}) 25
Check that :trac:`20490` is fixed::
sage: R.<a,b> = LaurentPolynomialRing(ZZ) sage: p = a*~a sage: p._fraction_pair() (a, a) sage: p == R.one() True sage: hash(p) 1
Check that :trac:`23864` is fixed (compatibility with integers, rationals and polynomial rings)::
sage: L = LaurentPolynomialRing(QQ, 'x0,x1,x2') sage: hash(L.zero()) 0 sage: hash(L.one()) 1 sage: hash(-L.one()) -2 sage: hash(L(1/2)) == hash(1/2) True
sage: R = PolynomialRing(QQ, 'x0,x1,x2') sage: x0,x1,x2 = R.gens() sage: hash(x0) == hash(L(x0)) True sage: hash(1 - 7*x0 + x1*x2) == hash(L(1 - 7*x0 + x1*x2)) True """ # we reimplement the hash from multipolynomial to handle negative exponents # (see multi_polynomial.pyx) cdef long exponent cdef int p cdef long c_hash
cdef _new_c(self): """ Returns a new Laurent polynomial
EXAMPLES::
sage: L.<x,y> = LaurentPolynomialRing(QQ) # indirect doctest sage: x*y x*y """ cdef LaurentPolynomial_mpair ans
def _normalize(self, i=None): """ Removes the common monomials from self._poly and stores them in self._mon
INPUT:
- ``i`` -- an integer
EXAMPLES::
sage: L.<x,y> = LaurentPolynomialRing(QQ) sage: f = x*y + 2*y*x^2 + y # indirect doctest sage: f.factor() # Notice the y has been factored out. (y) * (2*x^2 + x + 1)
Check that :trac:`23864` has been fixed::
sage: L.zero()._normalize() """
else: else: self._poly = self._poly // self._poly.parent().gen(i) self._mon = self._mon.eadd_p(e, i)
def _dict(self): """ EXAMPLES::
sage: L.<w,z> = LaurentPolynomialRing(QQ) sage: a = w^2*z^-1+3; a w^2*z^-1 + 3 sage: d = a._dict() sage: keys = list(sorted(d)); keys [(0, 0), (2, -1)] sage: d[keys[0]] 3 sage: d[keys[1]] 1
""" else:
def _compute_polydict(self): """ EXAMPLES::
sage: L.<w,z> = LaurentPolynomialRing(QQ) sage: a = w^2*z^-1+3 sage: a._compute_polydict() """
def is_unit(self): """ Return ``True`` if ``self`` is a unit.
The ground ring is assumed to be an integral domain.
This means that the Laurent polynomial is a monomial with unit coefficient.
EXAMPLES::
sage: L.<x,y> = LaurentPolynomialRing(QQ) sage: (x*y/2).is_unit() True sage: (x + y).is_unit() False sage: (L.zero()).is_unit() False sage: (L.one()).is_unit() True
sage: L.<x,y> = LaurentPolynomialRing(ZZ) sage: (2*x*y).is_unit() False """
def _repr_(self): """ EXAMPLES::
sage: L.<x,y> = LaurentPolynomialRing(QQ) sage: f = x^2 + x*y/2 + 2*y^-1 sage: f._repr_() 'x^2 + 1/2*x*y + 2*y^-1' """ except AttributeError: key = None
def _latex_(self): r""" EXAMPLES::
sage: L.<w,z> = LaurentPolynomialRing(QQ) sage: a = w^2*z^-1+3; a w^2*z^-1 + 3 sage: latex(a) w^{2} z^{-1} + 3
TESTS::
sage: L.<lambda2, y2> = LaurentPolynomialRing(QQ) sage: latex(1/lambda2 + y2^(-3)) \lambda_{2}^{-1} + y_{2}^{-3} """ except AttributeError: key = None
cpdef long number_of_terms(self) except -1: """ Return the number of non-zero coefficients of self. Also called weight, hamming weight or sparsity.
EXAMPLES::
sage: R.<x, y> = LaurentPolynomialRing(ZZ) sage: f = x^3 - y sage: f.number_of_terms() 2 sage: R(0).number_of_terms() 0 sage: f = (x+1/y)^100 sage: f.number_of_terms() 101
The method :meth:`hamming_weight` is an alias::
sage: f.hamming_weight() 101 """
def __invert__(LaurentPolynomial_mpair self): """ Return the inverse of ``self``.
This treats monomials specially so they remain Laurent polynomials; the inverse of any other polynomial is an element of the rational function field.
TESTS::
sage: L.<x,y> = LaurentPolynomialRing(ZZ) sage: f = ~x sage: parent(f) Multivariate Laurent Polynomial Ring in x, y over Integer Ring sage: parent(f.coefficients()[0]) is parent(f).base_ring() True sage: g = ~(2*x) sage: parent(g) Multivariate Laurent Polynomial Ring in x, y over Rational Field sage: parent(g.coefficients()[0]) is parent(g).base_ring() True """ cdef ETuple e
def __pow__(LaurentPolynomial_mpair self, n, m): """ EXAMPLES::
sage: L.<x,y> = LaurentPolynomialRing(QQ) sage: f = x + y sage: f^2 x^2 + 2*x*y + y^2 sage: f^(-1) 1/(x + y)
TESTS:
Check that :trac:`2952` is fixed::
sage: R.<q> = QQ[] sage: L.<x,y,z> = LaurentPolynomialRing(R) sage: f = (x+y+z^-1)^2 sage: f.substitute(z=1) x^2 + 2*x*y + y^2 + 2*x + 2*y + 1 """ cdef LaurentPolynomial_mpair ans
def __getitem__(self, n): r""" Return the coefficient of `x^n = x_1^{n_1} \cdots x_k^{n_k}` where `n` is a tuple of length `k` and `k` is the number of variables.
If the number of inputs is not equal to the number of variables, this raises a ``TypeError``.
EXAMPLES::
sage: P.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = (y^2 - x^9 - 7*x*y^3 + 5*x*y)*x^-3 + x*z; f -x^6 + x*z - 7*x^-2*y^3 + 5*x^-2*y + x^-3*y^2 sage: f[6,0,0] -1 sage: f[-2,3,0] -7 sage: f[-1,4,2] 0 sage: f[1,0,1] 1 sage: f[6] Traceback (most recent call last): ... TypeError: Must have exactly 3 inputs sage: f[6,0] Traceback (most recent call last): ... TypeError: Must have exactly 3 inputs sage: f[6,0,0,0] Traceback (most recent call last): ... TypeError: Must have exactly 3 inputs """ raise TypeError("Multivariate Laurent polynomials are not iterable")
def __iter__(self): """ Iterate through all terms by returning a list of the coefficient and the corresponding monomial.
EXAMPLES::
sage: P.<x,y> = LaurentPolynomialRing(QQ) sage: f = (y^2 - x^9 - 7*x*y^3 + 5*x*y)*x^-3 sage: list(f) # indirect doctest [(-1, x^6), (1, x^-3*y^2), (5, x^-2*y), (-7, x^-2*y^3)] """
def monomials(self): """ Return the list of monomials in ``self``.
EXAMPLES::
sage: P.<x,y> = LaurentPolynomialRing(QQ) sage: f = (y^2 - x^9 - 7*x*y^3 + 5*x*y)*x^-3 sage: f.monomials() [x^6, x^-3*y^2, x^-2*y, x^-2*y^3] """
def monomial_coefficient(self, mon): """ Return the coefficient in the base ring of the monomial ``mon`` in ``self``, where ``mon`` must have the same parent as ``self``.
This function contrasts with the function :meth:`coefficient()` which returns the coefficient of a monomial viewing this polynomial in a polynomial ring over a base ring having fewer variables.
INPUT:
- ``mon`` - a monomial
.. SEEALSO::
For coefficients in a base ring of fewer variables, see :meth:`coefficient()`.
EXAMPLES::
sage: P.<x,y> = LaurentPolynomialRing(QQ) sage: f = (y^2 - x^9 - 7*x*y^3 + 5*x*y)*x^-3 sage: f.monomial_coefficient(x^-2*y^3) -7 sage: f.monomial_coefficient(x^2) 0 """ raise TypeError("Input must have the same parent")
def constant_coefficient(self): """ Return the constant coefficient of ``self``.
EXAMPLES::
sage: P.<x,y> = LaurentPolynomialRing(QQ) sage: f = (y^2 - x^9 - 7*x*y^2 + 5*x*y)*x^-3; f -x^6 - 7*x^-2*y^2 + 5*x^-2*y + x^-3*y^2 sage: f.constant_coefficient() 0 sage: f = (x^3 + 2*x^-2*y+y^3)*y^-3; f x^3*y^-3 + 1 + 2*x^-2*y^-2 sage: f.constant_coefficient() 1 """
def coefficient(self, mon): r""" Return the coefficient of ``mon`` in ``self``, where ``mon`` must have the same parent as ``self``.
The coefficient is defined as follows. If `f` is this polynomial, then the coefficient `c_m` is sum:
.. MATH::
c_m := \sum_T \frac{T}{m}
where the sum is over terms `T` in `f` that are exactly divisible by `m`.
A monomial `m(x,y)` 'exactly divides' `f(x,y)` if `m(x,y) | f(x,y)` and neither `x \cdot m(x,y)` nor `y \cdot m(x,y)` divides `f(x,y)`.
INPUT:
- ``mon`` -- a monomial
OUTPUT:
Element of the parent of ``self``.
.. NOTE::
To get the constant coefficient, call :meth:`constant_coefficient()`.
EXAMPLES::
sage: P.<x,y> = LaurentPolynomialRing(QQ)
The coefficient returned is an element of the parent of ``self``; in this case, ``P``.
::
sage: f = 2 * x * y sage: c = f.coefficient(x*y); c 2 sage: c.parent() Multivariate Laurent Polynomial Ring in x, y over Rational Field
sage: P.<x,y> = LaurentPolynomialRing(QQ) sage: f = (y^2 - x^9 - 7*x*y^2 + 5*x*y)*x^-3; f -x^6 - 7*x^-2*y^2 + 5*x^-2*y + x^-3*y^2 sage: f.coefficient(y) 5*x^-2 sage: f.coefficient(y^2) -7*x^-2 + x^-3 sage: f.coefficient(x*y) 0 sage: f.coefficient(x^-2) -7*y^2 + 5*y sage: f.coefficient(x^-2*y^2) -7 sage: f.coefficient(1) -x^6 - 7*x^-2*y^2 + 5*x^-2*y + x^-3*y^2 """
def coefficients(self): """ Return the nonzero coefficients of this polynomial in a list. The returned list is decreasingly ordered by the term ordering of ``self.parent()``.
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ,order='degrevlex') sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 sage: f.coefficients() [4, 3, 2, 1] sage: L.<x,y,z> = LaurentPolynomialRing(QQ,order='lex') sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 sage: f.coefficients() [4, 1, 2, 3] """
def variables(self, sort=True): """ Return a tuple of all variables occurring in self.
INPUT:
- ``sort`` -- specifies whether the indices shall be sorted
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 sage: f.variables() (z, y, x) sage: f.variables(sort=False) #random (y, z, x) """
def dict(self): """ EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 sage: list(sorted(f.dict().items())) [((3, 1, 0), 3), ((4, 0, -2), 2), ((6, -7, 0), 1), ((7, 0, -1), 4)] """
def _fraction_pair(self): """ Return one representation of ``self`` as a pair ``(numerator, denominator)``.
Here both the numerator and the denominator are polynomials.
This is used for coercion into the fraction field.
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 sage: f._fraction_pair() (4*x^7*y^7*z + 3*x^3*y^8*z^2 + 2*x^4*y^7 + x^6*z^2, y^7*z^2) """ numer *= var[i] ** j else:
cpdef _add_(self, _right): """ Returns the Laurent polynomial self + right.
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = x + y^-1 sage: g = y + z sage: f + g x + y + z + y^-1 """ else: else:
cpdef _sub_(self, _right): """ Returns the Laurent polynomial self - right.
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = x + y^-1 sage: g = y + z + x sage: f - g -y - z + y^-1
""" cdef ETuple a, b else: else:
cpdef _div_(self, rhs): """ Return the division of ``self`` by ``rhs``.
If the denominator is not a unit, the result will be given in the fraction field.
EXAMPLES::
sage: R.<s,q,t> = LaurentPolynomialRing(QQ) sage: 1/s s^-1 sage: 1/(s*q) s^-1*q^-1 sage: 1/(s+q) 1/(s + q) sage: (1/(s+q)).parent() Fraction Field of Multivariate Polynomial Ring in s, q, t over Rational Field sage: (1/(s*q)).parent() Multivariate Laurent Polynomial Ring in s, q, t over Rational Field sage: (s+q)/(q^2*t^(-2)) s*q^-2*t^2 + q^-1*t^2 """ raise ZeroDivisionError else:
def is_monomial(self): """ Return True if this element is a monomial.
EXAMPLES::
sage: k.<y,z> = LaurentPolynomialRing(QQ) sage: z.is_monomial() True sage: k(1).is_monomial() True sage: (z+1).is_monomial() False sage: (z^-2909).is_monomial() True sage: (38*z^-2909).is_monomial() False """
cpdef _neg_(self): """ Returns -self.
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = x + y^-1 sage: -f -x - y^-1
"""
cpdef _lmul_(self, Element right): """ Returns self * right where right is in self's base ring.
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = x + y^-1 sage: f*(1/2) 1/2*x + 1/2*y^-1
"""
cpdef _rmul_(self, Element left): """ Returns left*self where left is in self's base ring.
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = x + y^-1 sage: (1/2)*f 1/2*x + 1/2*y^-1
"""
cpdef _mul_(self, right): """ Return self*right.
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = x + y^-1 sage: g = y + z sage: f*g x*y + x*z + 1 + y^-1*z """
cpdef _floordiv_(self, right): """ Perform division with remainder and return the quotient.
EXAMPLES::
sage: L.<x,y> = LaurentPolynomialRing(QQ) sage: f = x^3 + y^-3 sage: g = y + x sage: f // g x^5*y^-3 - x^4*y^-2 + x^3*y^-1
sage: h = x + y^(-1) sage: f // h x^2 - x*y^-1 + y^-2 sage: h * (f // h) == f True sage: f // 1 x^3 + y^-3 sage: 1 // f 0
TESTS:
Check that :trac:`19357` is fixed::
sage: x // y x*y^-1
Check that :trac:`21999` is fixed::
sage: L.<a,b> = LaurentPolynomialRing(QQbar) sage: (a+a*b) // a b + 1 """
@coerce_binop def quo_rem(self, right): """ Divide this Laurent polynomial by ``right`` and return a quotient and a remainder.
INPUT:
- ``right`` -- a Laurent polynomial
OUTPUT:
A pair of Laurent polynomials.
EXAMPLES::
sage: R.<s, t> = LaurentPolynomialRing(QQ) sage: (s^2-t^2).quo_rem(s-t) (s + t, 0) sage: (s^-2-t^2).quo_rem(s-t) (s + t, -s^4 + 1) sage: (s^-2-t^2).quo_rem(s^-1-t) (t + s^-1, 0) """
cpdef _richcmp_(self, right, int op): """ EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = x + y^-1 sage: g = y + z sage: f == f True sage: f == g False sage: f == 2 False """
def exponents(self): """ Returns a list of the exponents of self.
EXAMPLES::
sage: L.<w,z> = LaurentPolynomialRing(QQ) sage: a = w^2*z^-1+3; a w^2*z^-1 + 3 sage: e = a.exponents() sage: e.sort(); e [(0, 0), (2, -1)]
"""
def degree(self,x=None): """ Returns the degree of x in self
EXAMPLES::
sage: R.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 sage: f.degree(x) 7 sage: f.degree(y) 1 sage: f.degree(z) 0 """
raise TypeError("x must be a generator of parent")
def has_inverse_of(self, i): """ INPUT:
- ``i`` -- The index of a generator of ``self.parent()``
OUTPUT:
Returns True if self contains a monomial including the inverse of ``self.parent().gen(i)``, False otherwise.
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 sage: f.has_inverse_of(0) False sage: f.has_inverse_of(1) True sage: f.has_inverse_of(2) True """ raise TypeError("argument is not the index of a generator") return False
def has_any_inverse(self): """ Returns True if self contains any monomials with a negative exponent, False otherwise.
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 sage: f.has_any_inverse() True sage: g = x^2 + y^2 sage: g.has_any_inverse() False """
def __call__(self, *x, **kwds): """ Compute value of ``self`` at ``x``.
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = x + 2*y + 3*z sage: f(1,1,1) 6 sage: f = x^-1 + y + z sage: f(0,1,1) Traceback (most recent call last): ... ZeroDivisionError
TESTS::
sage: f = x + 2*y + 3*z sage: f(2) Traceback (most recent call last): ... TypeError: number of arguments does not match the number of generators in parent sage: f(2,0) Traceback (most recent call last): ... TypeError: number of arguments does not match the number of generators in parent sage: f( (1,1,1) ) 6 """ return f(*x) else:
" of generators in parent")
#Check to make sure that we aren't dividing by zero cdef int m
def subs(self, in_dict=None, **kwds): """ Substitute some variables in this Laurent polynomial.
Variable/value pairs for the substitution may be given as a dictionary or via keyword-value pairs. If both are present, the latter take precedence.
INPUT:
- ``in_dict`` -- dictionary (optional)
- ``**kwargs`` -- keyword arguments
OUTPUT:
A Laurent polynomial.
EXAMPLES::
sage: L.<x, y, z> = LaurentPolynomialRing(QQ) sage: f = x + 2*y + 3*z sage: f.subs(x=1) 2*y + 3*z + 1 sage: f.subs(y=1) x + 3*z + 2 sage: f.subs(z=1) x + 2*y + 3 sage: f.subs(x=1, y=1, z=1) 6
sage: f = x^-1 sage: f.subs(x=2) 1/2 sage: f.subs({x: 2}) 1/2
sage: f = x + 2*y + 3*z sage: f.subs({x: 1, y: 1, z: 1}) 6 sage: f.substitute(x=1, y=1, z=1) 6
TESTS::
sage: f = x + 2*y + 3*z sage: f(q=10) x + 2*y + 3*z
sage: x.subs({x: 2}, x=1) 1 """
def is_constant(self): r""" Return whether this Laurent polynomial is constant.
EXAMPLES::
sage: L.<a, b> = LaurentPolynomialRing(QQ) sage: L(0).is_constant() True sage: L(42).is_constant() True sage: a.is_constant() False sage: (1/b).is_constant() False """
def _symbolic_(self, R): """ EXAMPLES::
sage: R.<x,y> = LaurentPolynomialRing(QQ) sage: f = x^3 + y/x sage: g = f._symbolic_(SR); g (x^4 + y)/x sage: g(x=2,y=2) 9
sage: g = SR(f) sage: g(x=2,y=2) 9 """
def derivative(self, *args): r""" The formal derivative of this Laurent polynomial, with respect to variables supplied in args.
Multiple variables and iteration counts may be supplied; see documentation for the global derivative() function for more details.
.. SEEALSO::
:meth:`_derivative`
EXAMPLES::
sage: R = LaurentPolynomialRing(ZZ,'x, y') sage: x, y = R.gens() sage: t = x**4*y+x*y+y+x**(-1)+y**(-3) sage: t.derivative(x, x) 12*x^2*y + 2*x^-3 sage: t.derivative(y, 2) 12*y^-5 """
# add .diff(), .differentiate() as aliases for .derivative() diff = differentiate = derivative
def _derivative(self, var=None): """ Computes formal derivative of this Laurent polynomial with respect to the given variable.
If var is among the generators of this ring, the derivative is with respect to the generator. Otherwise, _derivative(var) is called recursively for each coefficient of this polynomial.
.. SEEALSO:: :meth:`derivative`
EXAMPLES::
sage: R = LaurentPolynomialRing(ZZ,'x, y') sage: x, y = R.gens() sage: t = x**4*y+x*y+y+x**(-1)+y**(-3) sage: t._derivative(x) 4*x^3*y + y - x^-2 sage: t._derivative(y) x^4 + x + 1 - 3*y^-4
sage: R = LaurentPolynomialRing(QQ['z'],'x') sage: z = R.base_ring().gen() sage: x = R.gen() sage: t = 33*z*x**4+x**(-1) sage: t._derivative(z) 33*x^4 sage: t._derivative(x) -x^-2 + 132*z*x^3 """ raise ValueError("must specify which variable to differentiate " "with respect to")
# check if var is one of the generators except ValueError: # call _derivative() recursively on coefficients return P({m: c._derivative(var) for (m, c) in self.dict().iteritems()})
# compute formal derivative with respect to generator
def is_univariate(self): """ Return ``True`` if this is a univariate or constant Laurent polynomial, and ``False`` otherwise.
EXAMPLES::
sage: R.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = (x^3 + y^-3)*z sage: f.is_univariate() False sage: g = f(1,y,4) sage: g.is_univariate() True sage: R(1).is_univariate() True """
def univariate_polynomial(self, R=None): """ Returns a univariate polynomial associated to this multivariate polynomial.
INPUT:
- ``R`` - (default: ``None``) a univariate Laurent polynomial ring
If this polynomial is not in at most one variable, then a ``ValueError`` exception is raised. The new polynomial is over the same base ring as the given ``LaurentPolynomial`` and in the variable ``x`` if no ring ``R`` is provided.
EXAMPLES::
sage: R.<x, y> = LaurentPolynomialRing(ZZ) sage: f = 3*x^2 - 2*y^-1 + 7*x^2*y^2 + 5 sage: f.univariate_polynomial() Traceback (most recent call last): ... TypeError: polynomial must involve at most one variable sage: g = f(10,y); g 700*y^2 + 305 - 2*y^-1 sage: h = g.univariate_polynomial(); h -2*y^-1 + 305 + 700*y^2 sage: h.parent() Univariate Laurent Polynomial Ring in y over Integer Ring sage: g.univariate_polynomial(LaurentPolynomialRing(QQ,'z')) -2*z^-1 + 305 + 700*z^2
Here's an example with a constant multivariate polynomial::
sage: g = R(1) sage: h = g.univariate_polynomial(); h 1 sage: h.parent() Univariate Laurent Polynomial Ring in x over Integer Ring """ else:
#construct ring if none
def factor(self): """ Returns a Laurent monomial (the unit part of the factorization) and a factored multi-polynomial.
EXAMPLES::
sage: L.<x,y,z> = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 sage: f.factor() (x^3*y^-7*z^-2) * (4*x^4*y^7*z + 3*y^8*z^2 + 2*x*y^7 + x^3*z^2) """
else:
|