# Ticket #11726: trac_11726-univariate_Laurent_polynomials-ts.patch

File trac_11726-univariate_Laurent_polynomials-ts.patch, 88.5 KB (added by tscrim, 8 years ago)
• ## sage/algebras/iwahori_hecke_algebra.py

# HG changeset patch
# Parent f4e436887a4752799ac31dffec9ecf643faac3ba
#11726: Implement univariate Laurent polynomial rings

diff --git a/sage/algebras/iwahori_hecke_algebra.py b/sage/algebras/iwahori_hecke_algebra.py
 a from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation from sage.categories.realizations import Realizations, Category_realization_of_parent from sage.categories.all import AlgebrasWithBasis, FiniteDimensionalAlgebrasWithBasis, CoxeterGroups from sage.rings.polynomial.polydict import ETuple from sage.rings.all import ZZ from sage.combinat.root_system.weyl_group import WeylGroup class IwahoriHeckeAlgebra(Parent, Unique sage: T1 + T2 T1 + T2 sage: T1*T1 (v^2-1)*T1 + v^2 -(1-v^2)*T1 + v^2 sage: (T1 + T2)*T3 + T1*T1 - (v + v^-1)*T2 T3*T1 + (v^2-1)*T1 + T2*T3 + (-v-v^-1)*T2 + v^2 T3*T1 - (1-v^2)*T1 + T2*T3 - (v^-1+v)*T2 + v^2 sage: Cp(T1) v*Cp[s1] + (-1) v*Cp[s1] - 1 sage: Cp((v^1 - 1)*T1*T2 - T3) (v^3-v^2)*Cp[s1*s2] + (-v^2+v)*Cp[s1] + (-v^2+v)*Cp[s2] + (-v)*Cp[s3] + v -(v^2-v^3)*Cp[s1*s2] + (v-v^2)*Cp[s1] + (v-v^2)*Cp[s2] - v*Cp[s3] + v sage: C(T1) v*C[s1] + v^2 sage: p = C(T2*T3 - v*T1); p (-v^2)*C[s1] + v^2*C[s2*s3] + v^3*C[s2] + v^3*C[s3] + (v^4-v^3) -v^2*C[s1] + v^2*C[s2*s3] + v^3*C[s2] + v^3*C[s3] - (v^3-v^4) sage: Cp(p) (-v^2)*Cp[s1] + v^2*Cp[s2*s3] + (-v)*Cp[s2] + (-v)*Cp[s3] + (v+1) -v^2*Cp[s1] + v^2*Cp[s2*s3] - v*Cp[s2] - v*Cp[s3] + (1+v) sage: Cp(T2*T3 - v*T1) (-v^2)*Cp[s1] + v^2*Cp[s2*s3] + (-v)*Cp[s2] + (-v)*Cp[s3] + (v+1) -v^2*Cp[s1] + v^2*Cp[s2*s3] - v*Cp[s2] - v*Cp[s3] + (1+v) In addition to explicitly creating generators, we have two shortcuts to basis elements. The first is by using elements of the underlying Coxeter class IwahoriHeckeAlgebra(Parent, Unique sage: T(Cp[1]) (v^-1)*T1 + (v^-1) sage: T(C[1]) (v^-1)*T1 + (-v) (v^-1)*T1 - v sage: C(Cp[1]) C[s1] + (v+v^-1) C[s1] + (v^-1+v) sage: Cp(C[1]) Cp[s1] + (-v-v^-1) Cp[s1] - (v^-1+v) sage: all(C[x] == C[x].bar() for x in W) # long time True sage: all(Cp[x] == Cp[x].bar() for x in W) # long time class IwahoriHeckeAlgebra(Parent, Unique sage: V1,V2 = H1.algebra_generators() sage: W1,W2 = H1.inverse_generators() sage: [W1,W2] [(q^-1)*V1 + (-1+q^-1), (q^-1)*V2 + (-1+q^-1)] [(q^-1)*V1 + (q^-1-1), (q^-1)*V2 + (q^-1-1)] sage: V1*W1, W2*V2 (1, 1) """ class IwahoriHeckeAlgebra(Parent, Unique sage: C(v^-1*T(s1) - v) C[s1] sage: C(T(s1*s2)+T(s1)+T(s2)+1) v^2*C[s1*s2] + (v^3+v)*C[s1] + (v^3+v)*C[s2] + (v^4+2*v^2+1) v^2*C[s1*s2] + (v+v^3)*C[s1] + (v+v^3)*C[s2] + (1+2*v^2+v^4) sage: C(T(s1*s2*s1)) v^3*C[s1*s2*s1] + v^4*C[s1*s2] + v^4*C[s2*s1] + v^5*C[s1] + v^5*C[s2] + v^6 """ class IwahoriHeckeAlgebra(Parent, Unique sage: T = H.T() sage: Cp = H.Cp() sage: T.to_C_prime_basis(s1) v*Cp[s1] + (-1) v*Cp[s1] - 1 sage: Cp(T(s1)) v*Cp[s1] + (-1) v*Cp[s1] - 1 sage: Cp(T(s1)+1) v*Cp[s1] sage: Cp(T(s1*s2)+T(s1)+T(s2)+1) v^2*Cp[s1*s2] sage: Cp(T(s1*s2*s1)) v^3*Cp[s1*s2*s1] + (-v^2)*Cp[s1*s2] + (-v^2)*Cp[s2*s1] + v*Cp[s1] + v*Cp[s2] + (-1) v^3*Cp[s1*s2*s1] - v^2*Cp[s1*s2] - v^2*Cp[s2*s1] + v*Cp[s1] + v*Cp[s2] - 1 """ A = self.realization_of() Cp = A.C_prime() class IwahoriHeckeAlgebra(Parent, Unique sage: s1,s2,s3 = W.simple_reflections() sage: T = H.T() sage: b = T.bar_on_basis(s1*s2*s3); b (v^-6)*T1*T2*T3 + (-v^-4+v^-6)*T1*T2 + (-v^-4+v^-6)*T3*T1 + (v^-2-2*v^-4+v^-6)*T1 + (-v^-4+v^-6)*T2*T3 + (v^-2-2*v^-4+v^-6)*T2 + (v^-2-2*v^-4+v^-6)*T3 + (-1+3*v^-2-3*v^-4+v^-6) (v^-6)*T1*T2*T3 + (v^-6-v^-4)*T1*T2 + (v^-6-v^-4)*T3*T1 + (v^-6-2*v^-4+v^-2)*T1 + (v^-6-v^-4)*T2*T3 + (v^-6-2*v^-4+v^-2)*T2 + (v^-6-2*v^-4+v^-2)*T3 + (v^-6-3*v^-4+3*v^-2-1) sage: b.bar() T1*T2*T3 """ class IwahoriHeckeAlgebra(Parent, Unique sage: H = IwahoriHeckeAlgebra("A2", q).T() sage: [T1,T2] = H.algebra_generators() sage: x = (T1*T2).inverse(); x (q^-2)*T2*T1 + (-q^-1+q^-2)*T1 + (-q^-1+q^-2)*T2 + (1-2*q^-1+q^-2) (q^-2)*T2*T1 + (q^-2-q^-1)*T1 + (q^-2-q^-1)*T2 + (q^-2-2*q^-1+1) sage: x*T1*T2 1 class IwahoriHeckeAlgebra(Parent, Unique sage: H = IwahoriHeckeAlgebra("A2", q).T() sage: T1,T2 = H.algebra_generators() sage: ~(T1*T2) (q^-2)*T2*T1 + (-q^-1+q^-2)*T1 + (-q^-1+q^-2)*T2 + (1-2*q^-1+q^-2) (q^-2)*T2*T1 + (q^-2-q^-1)*T1 + (q^-2-q^-1)*T2 + (q^-2-2*q^-1+1) sage: (T1*T2)^(-1) (q^-2)*T2*T1 + (-q^-1+q^-2)*T1 + (-q^-1+q^-2)*T2 + (1-2*q^-1+q^-2) (q^-2)*T2*T1 + (q^-2-q^-1)*T1 + (q^-2-q^-1)*T2 + (q^-2-2*q^-1+1) """ if len(self) != 1: raise NotImplementedError("inverse only implemented for basis elements (monomials in the generators)"%self) class IwahoriHeckeAlgebra(Parent, Unique sage: T = H.T() sage: T1,T2,T3 = T.algebra_generators() sage: elt = T1.hecke_involution(); elt (-v^-2)*T1 -(v^-2)*T1 sage: elt.hecke_involution() T1 sage: elt = T1*T2 + (v^3 - v^-1 + 2)*T3*T1*T2*T3 sage: elt.hecke_involution() (-v^-7+2*v^-8+v^-11)*T1*T2*T3*T2 + (v^-4)*T1*T2 (v^-11+2*v^-8-v^-7)*T1*T2*T3*T2 + (v^-4)*T1*T2 sage: elt.hecke_involution().hecke_involution() == elt True """ class IwahoriHeckeAlgebra(Parent, Unique sage: H = IwahoriHeckeAlgebra(['A',2], v**2, v) sage: s1,s2 = H.coxeter_group().simple_reflections() sage: [H.Cp().product_on_basis(s1,x) for x in [s1,s2]] [(v+v^-1)*Cp[s1], Cp[s1*s2]] [(v^-1+v)*Cp[s1], Cp[s1*s2]] sage: [H.C().product_on_basis(s1,x) for x in [s1,s2]] [(-v-v^-1)*C[s1], C[s1*s2]] [-(v^-1+v)*C[s1], C[s1*s2]] """ return self(self.to_T_basis(w1) * self.to_T_basis(w2)) class IwahoriHeckeAlgebra(Parent, Unique sage: T = H.T() sage: Cp = H.Cp() sage: T(s1)**2 (v^2-1)*T1 + v^2 -(1-v^2)*T1 + v^2 sage: T(Cp(s1)) (v^-1)*T1 + (v^-1) sage: T(Cp(s1)*Cp(s2)*Cp(s1)) (v^-3)*T1*T2*T1 + (v^-3)*T1*T2 + (v^-3)*T2*T1 + (v^-1+v^-3)*T1 + (v^-3)*T2 + (v^-1+v^-3) (v^-3)*T1*T2*T1 + (v^-3)*T1*T2 + (v^-3)*T2*T1 + (v^-3+v^-1)*T1 + (v^-3)*T2 + (v^-3+v^-1) :: class IwahoriHeckeAlgebra(Parent, Unique sage: Cp(s1*s2*s1) Cp[s1*s2*s1] sage: Cp(s1)**2 (v+v^-1)*Cp[s1] (v^-1+v)*Cp[s1] sage: Cp(s1)*Cp(s2)*Cp(s1) Cp[s1*s2*s1] + Cp[s1] sage: Cp(s1)*Cp(s2)*Cp(s3)*Cp(s1)*Cp(s2) class IwahoriHeckeAlgebra(Parent, Unique sage: T(Cp(s1*s2*s1)) (v^-3)*T1*T2*T1 + (v^-3)*T1*T2 + (v^-3)*T2*T1 + (v^-3)*T1 + (v^-3)*T2 + (v^-3) sage: T(Cp(s2*s1*s3*s2)) (v^-4)*T2*T3*T1*T2 + (v^-4)*T1*T2*T1 + (v^-4)*T3*T1*T2 + (v^-4)*T1*T2 + (v^-4)*T2*T3*T1 + (v^-4)*T2*T1 + (v^-4)*T3*T1 + (v^-4)*T1 + (v^-4)*T2*T3*T2 + (v^-4)*T2*T3 + (v^-4)*T3*T2 + (v^-2+v^-4)*T2 + (v^-4)*T3 + (v^-2+v^-4) (v^-4)*T2*T3*T1*T2 + (v^-4)*T1*T2*T1 + (v^-4)*T3*T1*T2 + (v^-4)*T1*T2 + (v^-4)*T2*T3*T1 + (v^-4)*T2*T1 + (v^-4)*T3*T1 + (v^-4)*T1 + (v^-4)*T2*T3*T2 + (v^-4)*T2*T3 + (v^-4)*T3*T2 + (v^-4+v^-2)*T2 + (v^-4)*T3 + (v^-4+v^-2) """ A = self.realization_of() T = A.T() class IwahoriHeckeAlgebra(Parent, Unique while i < len(result): (x,c) = result.terms()[i].leading_item() deg = ETuple([-x.length()]) if deg in c.dict().keys(): mu = c.dict()[deg] else: mu = 0 if (mu != 0): mu = c[-x.length()] if mu != 0: result = result - mu * self.to_T_basis(x) else: i = i + 1 class IwahoriHeckeAlgebra(Parent, Unique sage: T = H.T() sage: C = H.C() sage: T(s1)**2 (v^2-1)*T1 + v^2 -(1-v^2)*T1 + v^2 sage: T(C(s1)) (v^-1)*T1 + (-v) (v^-1)*T1 - v sage: T(C(s1)*C(s2)*C(s1)) (v^-3)*T1*T2*T1 + (-v^-1)*T1*T2 + (-v^-1)*T2*T1 + (v+v^-1)*T1 + v*T2 + (-v^3-v) (v^-3)*T1*T2*T1 - (v^-1)*T1*T2 - (v^-1)*T2*T1 + (v^-1+v)*T1 + v*T2 - (v+v^3) :: class IwahoriHeckeAlgebra(Parent, Unique sage: C(s1*s2*s1) C[s1*s2*s1] sage: C(s1)**2 (-v-v^-1)*C[s1] -(v^-1+v)*C[s1] sage: C(s1)*C(s2)*C(s1) C[s1*s2*s1] + C[s1] class IwahoriHeckeAlgebra(Parent, Unique Check the defining property between C and C^{\prime}:: sage: T(C[1]) (v^-1)*T1 + (-v) (v^-1)*T1 - v sage: -T(Cp[1]).hecke_involution() (v^-1)*T1 + (-v) (v^-1)*T1 - v sage: T(Cp[1] + Cp[2]).hecke_involution() (-v^-1)*T1 + (-v^-1)*T2 + 2*v -(v^-1)*T1 - (v^-1)*T2 + 2*v sage: -T(C[1] + C[2]) (-v^-1)*T1 + (-v^-1)*T2 + 2*v -(v^-1)*T1 - (v^-1)*T2 + 2*v sage: Cp(-C[1].hecke_involution()) Cp[s1] sage: Cp(-C[1,2,3].hecke_involution()) class IwahoriHeckeAlgebra(Parent, Unique sage: T = H.T() sage: C = H.C() sage: C.to_T_basis(s1) (v^-1)*T1 + (-v) (v^-1)*T1 - v sage: C.to_T_basis(s1*s2) (v^-2)*T1*T2 + (-1)*T1 + (-1)*T2 + v^2 (v^-2)*T1*T2 - T1 - T2 + v^2 sage: C.to_T_basis(s1*s2*s1) (v^-3)*T1*T2*T1 + (-v^-1)*T1*T2 + (-v^-1)*T2*T1 + v*T1 + v*T2 + (-v^3) (v^-3)*T1*T2*T1 - (v^-1)*T1*T2 - (v^-1)*T2*T1 + v*T1 + v*T2 - v^3 sage: T(C(s1*s2*s1)) (v^-3)*T1*T2*T1 + (-v^-1)*T1*T2 + (-v^-1)*T2*T1 + v*T1 + v*T2 + (-v^3) (v^-3)*T1*T2*T1 - (v^-1)*T1*T2 - (v^-1)*T2*T1 + v*T1 + v*T2 - v^3 sage: T(C(s2*s1*s3*s2)) (v^-4)*T2*T3*T1*T2 + (-v^-2)*T1*T2*T1 + (-v^-2)*T3*T1*T2 + T1*T2 + (-v^-2)*T2*T3*T1 + T2*T1 + T3*T1 + (-v^2)*T1 + (-v^-2)*T2*T3*T2 + T2*T3 + T3*T2 + (-v^2-1)*T2 + (-v^2)*T3 + (v^4+v^2) (v^-4)*T2*T3*T1*T2 - (v^-2)*T1*T2*T1 - (v^-2)*T3*T1*T2 + T1*T2 - (v^-2)*T2*T3*T1 + T2*T1 + T3*T1 - v^2*T1 - (v^-2)*T2*T3*T2 + T2*T3 + T3*T2 - (1+v^2)*T2 - v^2*T3 + (v^2+v^4) """ # Treat our index as in the C' and then perform the Hecke #   involution since computationally they are the same class IwahoriHeckeAlgebraBases(Category_ sage: T = H.T() sage: T1,T2,T3 = T.algebra_generators() sage: T1.bar() (q^-1)*T1 + (-1+q^-1) (q^-1)*T1 + (q^-1-1) sage: T1.bar().bar() == T1 True Next on a multiple of generators:: sage: b = (T1*T2*T1).bar(); b (q^-3)*T1*T2*T1 + (-q^-2+q^-3)*T1*T2 + (-q^-2+q^-3)*T2*T1 + (q^-1-2*q^-2+q^-3)*T1 + (q^-1-2*q^-2+q^-3)*T2 + (-1+2*q^-1-2*q^-2+q^-3) (q^-3)*T1*T2*T1 + (q^-3-q^-2)*T1*T2 + (q^-3-q^-2)*T2*T1 + (q^-3-2*q^-2+q^-1)*T1 + (q^-3-2*q^-2+q^-1)*T2 + (q^-3-2*q^-2+2*q^-1-1) sage: b.bar() == T1*T2*T1 True class IwahoriHeckeAlgebraBases(Category_ sage: s = T1 + T2 sage: b = s.bar(); b (q^-1)*T1 + (q^-1)*T2 + (-2+2*q^-1) (q^-1)*T1 + (q^-1)*T2 + (2*q^-1-2) sage: b.bar() == s True class IwahoriHeckeAlgebraBases(Category_ sage: p = T1*T2 + (1-q+q^-1)*T3 - q^3*T1*T3 sage: p.bar() (q^-2)*T1*T2 + (-q^-5)*T3*T1 + (-q^-1+q^-2+q^-4-q^-5)*T1 + (-q^-1+q^-2)*T2 + (1+q^-1-q^-2+q^-4-q^-5)*T3 + (-q+1-q^-3+2*q^-4-q^-5) (q^-2)*T1*T2 - (q^-5)*T3*T1 - (q^-5-q^-4-q^-2+q^-1)*T1 + (q^-2-q^-1)*T2 - (q^-5-q^-4+q^-2-q^-1-1)*T3 - (q^-5-2*q^-4+q^-3-1+q) sage: p.bar().bar() == p True class IwahoriHeckeAlgebraBases(Category_ sage: Cp = H.Cp() sage: p = Cp[1]*Cp[3] + Cp[2] sage: q = p.hecke_involution(); q Cp[s3*s1] + (-v-v^-1)*Cp[s1] + (-1)*Cp[s2] + (-v-v^-1)*Cp[s3] + (v^2+v+2+v^-1+v^-2) Cp[s3*s1] - (v^-1+v)*Cp[s1] - Cp[s2] - (v^-1+v)*Cp[s3] + (v^-2+v^-1+2+v+v^2) sage: q.hecke_involution() == p True class IwahoriHeckeAlgebraBases(Category_ sage: C = H.C() sage: p = C[1]*C[3] + C[2] sage: q = p.hecke_involution(); q C[s3*s1] + (v+v^-1)*C[s1] + (-1)*C[s2] + (v+v^-1)*C[s3] + (v^2-v+2-v^-1+v^-2) C[s3*s1] + (v^-1+v)*C[s1] - C[s2] + (v^-1+v)*C[s3] + (v^-2-v^-1+2-v+v^2) sage: q.hecke_involution() == p True """
• ## sage/categories/pushout.py

diff --git a/sage/categories/pushout.py b/sage/categories/pushout.py
 a class LaurentPolynomialFunctor(Construct Defn: x |--> x + 2*y y |--> 3*x - y sage: F(f)(x*F(P).gen()^-2+y*F(P).gen()^3) (3*x - y)*t^3 + (x + 2*y)*t^-2 (x + 2*y)*t^-2 + (3*x - y)*t^3 """ rank = 9
• ## sage/combinat/kazhdan_lusztig.py

diff --git a/sage/combinat/kazhdan_lusztig.py b/sage/combinat/kazhdan_lusztig.py
 a class KazhdanLusztigPolynomial(UniqueRep sage: R. = LaurentPolynomialRing(QQ) sage: KL = KazhdanLusztigPolynomial(W,q) sage: KL.P(s2,s3*s2*s3*s1*s2) q + 1 1 + q A faster implementation (using the optional package Coxeter 3) is given by:: sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3 sage: W.kazhdan_lusztig_polynomial([2], [3,2,3,1,2])        # optional - coxeter3 q + 1 1 + q """ def __init__(self, W, q, trace=False): """ class KazhdanLusztigPolynomial(UniqueRep return self._base_ring.zero() p = sum(-self.R(x,t)*self.P(t,y) for t in self._coxeter_group.bruhat_interval(x,y) if t != x) tr = floor((y.length()-x.length()+1)/2) try: ret = p.truncate(tr) except StandardError: ret = laurent_polynomial_truncate(p, tr) ret = p.truncate(tr) if self._trace: print "    P(%s,%s)=%s"%(x, y, ret) return ret def laurent_polynomial_truncate(p, n): """ Truncate the Laurent polynomial p, returning only terms of degree less than n, similar to the truncate method for polynomials. EXAMPLES:: sage: from sage.combinat.kazhdan_lusztig import laurent_polynomial_truncate sage: P. = LaurentPolynomialRing(QQ) sage: laurent_polynomial_truncate((q+q^-1)^3+q^2*(q+q^-1)^4,3) 6*q^2 + 3*q + 4 + 3*q^-1 + q^-2 + q^-3 """ pdict = p._dict() dict = {} for k in pdict: if k[0] < n: dict[k] = pdict[k] return p.parent()(dict)
• ## sage/rings/laurent_series_ring_element.pyx

diff --git a/sage/rings/laurent_series_ring_element.pyx b/sage/rings/laurent_series_ring_element.pyx
 a import sage.rings.polynomial.polynomial_ import sage.misc.latex import sage.rings.ring_element as ring_element from sage.rings.integer import Integer from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial_univariate from sage.structure.element cimport Element, ModuleElement, RingElement, AlgebraElement def is_LaurentSeries(x): cdef class LaurentSeries(AlgebraElement): """ A Laurent Series. We consider a Laurent series of the form t^n \cdot f where f is a power series. INPUT: - parent -- a Laurent series ring - f -- a power series (or something can be coerced to one); note that f does *not* have to be a unit - n -- (default: 0) integer """ def __init__(self, parent, f, n=0): r""" Create the Laurent series t^n \cdot f. The default is n=0. INPUT: -  parent - a Laurent series ring -  f - a power series (or something can be coerced to one); note that f does *not* have to be a unit. -  n - integer (default 0) Initialize self. OUTPUT: a Laurent series cdef class LaurentSeries(AlgebraElement) """ AlgebraElement.__init__(self, parent) if PY_TYPE_CHECK(f, LaurentSeries): if isinstance(f, LaurentSeries): n += (f).__n if (f).__u._parent is parent.power_series_ring(): f = (f).__u else: f = parent.power_series_ring()((f).__u) elif not PY_TYPE_CHECK(f, PowerSeries): elif isinstance(f, LaurentPolynomial_univariate): f = f(parent.gen()) elif not isinstance(f, PowerSeries): f = parent.power_series_ring()(f) ## now this is a power series, over a different ring ... ## requires that power series rings with same vars over the cdef class LaurentSeries(AlgebraElement) sage: R. = LaurentSeriesRing(QQ) sage: f = t^-3 + t + 7*t^2 + O(t^5) sage: g = f.laurent_polynomial(); g 7*t^2 + t + t^-3 t^-3 + t + 7*t^2 sage: g.parent() Univariate Laurent Polynomial Ring in t over Rational Field """ cdef class LaurentSeries(AlgebraElement) def shift(self, k): r""" Returns this laurent series multiplied by the power t^n. Returns this Laurent series multiplied by the power t^n. Does not change this series. .. note:: .. NOTE:: Despite the fact that higher order terms are printed to the right in a power series, right shifting decreases the
• ## sage/rings/polynomial/laurent_polynomial.pxd

diff --git a/sage/rings/polynomial/laurent_polynomial.pxd b/sage/rings/polynomial/laurent_polynomial.pxd
 a from sage.rings.polynomial.polydict cimp from sage.rings.polynomial.multi_polynomial cimport MPolynomial from sage.rings.polynomial.polynomial_element cimport Polynomial cdef class LaurentPolynomial_univariate(CommutativeAlgebraElement): cpdef ModuleElement __u cdef long __n cdef class LaurentPolynomial_mpair(CommutativeAlgebraElement): cdef ETuple _mon cdef MPolynomial _poly
• ## sage/rings/polynomial/laurent_polynomial.pyx

diff --git a/sage/rings/polynomial/laurent_polynomial.pyx b/sage/rings/polynomial/laurent_polynomial.pyx
 a Elements of Laurent polynomial rings """ include "sage/ext/stdsage.pxi" import re from sage.rings.integer import Integer from sage.structure.element import is_Element from sage.structure.element import is_Element, coerce_binop from sage.misc.latex import latex import sage.misc.latex 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 cdef class LaurentPolynomial_univariate(CommutativeAlgebraElement): """ 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. = LaurentPolynomialRing(ZZ) sage: R([1,2,3]) 1 + 2*q + 3*q^2 sage: TestSuite(q^-3 + 3*q + 2).run() :: sage: S. = LaurentPolynomialRing(GF(5)) sage: 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 """ CommutativeAlgebraElement.__init__(self, parent) if isinstance(f, LaurentPolynomial_univariate): n += (f).__n if (f).__u._parent is parent.polynomial_ring(): f = (f).__u else: f = parent.polynomial_ring()((f).__u) elif (not isinstance(f, Polynomial)) or (parent is not f.parent()): if isinstance(f, dict): v = min(f.keys()) f = dict((i-v,c) for i,c in f.items()) n += v f = parent.polynomial_ring()(f) # self is that t^n * u: cdef long val self.__u = f self.__n = n self.__normalize() def __reduce__(self): """ Used in pickling. EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ) sage: elt = q^-3 + 2 + q sage: loads(dumps(elt)) == elt True """ return LaurentPolynomial_univariate, (self._parent, self.__u, self.__n) def change_ring(self, R): """ Return a copy of this Laurent polynomial, with coefficients in R. EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) sage: a = x^2 + 3*x^3 + 5*x^-1 sage: a.change_ring(GF(3)) 2*x^-1 + x^2 """ return self.parent().change_ring(R)(self) def is_unit(self): """ Return True if this Laurent polynomial is a unit in this ring. EXAMPLES:: sage: R. = 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. = LaurentPolynomialRing(ZZ) sage: g = 2*s sage: g.is_unit() False sage: 1/g 1/(2*s) ALGORITHM: A Laurent polynomial is a unit if and only if its "unit part" is a unit. """ return self.__u.is_term() and self.__u.coefficients()[0].is_unit() def is_zero(self): """ Return 1 if self is 0, else return 0. EXAMPLES:: sage: R. = 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 """ return self.__u.is_zero() def __nonzero__(self): """ Check if self is non-zero. EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) sage: f = 1/x + x + x^2 + 3*x^4 sage: not f False sage: z = 0*f sage: not z True """ return not not self.__u def _im_gens_(self, codomain, im_gens): """ Return the image of self under the morphism defined by im_gens in codomain. EXAMPLES:: sage: R. = 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 """ return codomain(self(im_gens[0])) 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. = LaurentPolynomialRing(QQ) sage: elt = t^2 + t^4 # indirect doctest sage: elt.polynomial_construction() (t^2 + 1, 2) """ from sage.rings.infinity import infinity if self.is_zero(): return v = self.__u.valuation() if v != 0 and v != infinity: self.__n += v self.__u = self.__u >> v def _repr_(self): """ Return a string representation of self. EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) sage: 2 + (2/3)*t^3 2 + 2/3*t^3 """ if self.is_zero(): return "0" s = " " v = self.__u.list() valuation = self.__n m = len(v) X = self._parent.variable_name() atomic_repr = self._parent.base_ring()._repr_option('element_is_atomic') first = True for n in xrange(m): x = v[n] e = n + valuation x = str(x) if x != '0': if not first: s += " + " if not atomic_repr and (x[1:].find("+") != -1 or x[1:].find("-") != -1): x = "(%s)"%x if e == 1: var = "*%s"%X elif e == 0: var = "" else: var = "*%s^%s"%(X,e) s += "%s%s"%(x,var) first = False s = s.replace(" + -", " - ") s = s.replace(" 1*"," ") s = s.replace(" -1*", " -") return s[1:] def _latex_(self): r""" EXAMPLES:: sage: R. = 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.=PolynomialRing(QQ) sage: T.=LaurentPolynomialRing(R) sage: y = a*x+b*x sage: y._latex_() '\\left(a + b\\right)x' sage: latex(y) \left(a + b\right)x """ if self.is_zero(): return "0" s = " " v = self.__u.list() valuation = self.__n m = len(v) X = self._parent.latex_variable_names()[0] atomic_repr = self._parent.base_ring()._repr_option('element_is_atomic') first = True for n in xrange(m): x = v[n] e = n + valuation x = sage.misc.latex.latex(x) if x != '0': if not first: s += " + " if not atomic_repr and e > 0 and (x[1:].find("+") != -1 or x[1:].find("-") != -1): x = "\\left(%s\\right)"%x if e == 1: var = "|%s"%X elif e == 0: var = "" elif e > 0: var = "|%s^{%s}"%(X,e) if e >= 0: s += "%s%s"%(x,var) else: # negative e if e == -1: s += "\\frac{%s}{%s}"%(x, X) else: s += "\\frac{%s}{%s^{%s}}"%(x, X,-e) first = False s = s.replace(" + -", " - ") s = s.replace(" 1|"," ") s = s.replace(" -1|", " -") s = s.replace("|","") return s[1:] def __hash__(self): """ Return the hash of self. EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) sage: f = -5/t^(10) + t + t^2 - 10/3*t^3 sage: hash(f) == hash(f) True """ return hash(self.__u) ^ self.__n def __getitem__(self, i): """ Return the coefficient of t^i. EXAMPLES:: sage: R. = 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 """ return self.__u[i-self.__n] def __getslice__(self, i, j): """ Return the Laurent polynomial \sum_{k=i}^{j-1} c_k t^k where self is \sum_k c_k t^k. EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) 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 sage: f[-10:2] -5*t^-10 + 1/3 + t sage: f[0:] 1/3 + t + t^2 - 10/3*t^3 """ if j > self.__u.degree(): j = self.__u.degree() f = self.__u[i-self.__n:j-self.__n] return LaurentPolynomial_univariate(self._parent, f, self.__n) def __iter__(self): """ Iterate through the coefficients from the first nonzero one to the last nonzero one. EXAMPLES:: sage: R. = 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 """ return iter(self.__u) def dict(self): """ Return a dictionary representing self. EXAMPLES:: sage: R. = ZZ[] sage: Q. = 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() {0: x^9, -6: 3*x^3*y^2, 2: 1, -3: 3*x^6*y, -9: y^3} """ return dict(zip(self.exponents(), self.coefficients())) def coefficients(self): """ Return the nonzero coefficients of self. EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) sage: f = -5/t^(2) + t + t^2 - 10/3*t^3 sage: f.coefficients() [-5, 1, 1, -10/3] """ return self.__u.coefficients() def exponents(self): """ Return the exponents appearing in self with nonzero coefficients. EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) sage: f = -5/t^(2) + t + t^2 - 10/3*t^3 sage: f.exponents() [-2, 1, 2, 3] """ return [i+self.__n for i in self.__u.exponents()] def __setitem__(self, n, value): """ EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) sage: f = t^2 + t^-3 sage: f[2] = 5 Traceback (most recent call last): ... IndexError: Laurent polynomials are immutable """ raise 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. = LaurentPolynomialRing(QQ) sage: f = t^2 + t^-3 sage: f._unsafe_mutate(2, 3) sage: f t^-3 + 3*t^2 """ j = i - self.__n if j >= 0: self.__u._unsafe_mutate(j, value) 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) self.__normalize() cpdef ModuleElement _add_(self, ModuleElement right_m): """ Add two Laurent polynomials with the same parent. EXAMPLES:: sage: R. = 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 LaurentPolynomial_univariate right = right_m cdef long m # 1. Special case when one or the other is 0. if not right: return self if not self: return right # 2. Align the unit parts. if self.__n < right.__n: m = self.__n f1 = self.__u f2 = right.__u << right.__n - m elif self.__n > right.__n: m = right.__n f1 = self.__u << self.__n - m f2 = right.__u else: m = self.__n f1 = self.__u f2 = right.__u # 3. Add return LaurentPolynomial_univariate(self._parent, f1 + f2, m) cpdef ModuleElement _iadd_(self, ModuleElement right_m): """ EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) sage: f = t+t sage: f += t; f 3*t sage: f += t*t; f 3*t + t^2 """ cdef LaurentPolynomial_univariate right = right_m if self.__n == right.__n: self.__u += right.__u return self else: return self._add_(right) cpdef ModuleElement _sub_(self, ModuleElement right_m): """ Subtract two Laurent polynomials with the same parent. EXAMPLES:: sage: R. = 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 LaurentPolynomial_univariate right = right_m cdef long m # 1. Special case when one or the other is 0. if not right: return self if not self: return -right # 2. Align the unit parts. if self.__n < right.__n: m = self.__n f1 = self.__u f2 = right.__u << right.__n - m else: m = right.__n f1 = self.__u << self.__n - m f2 = right.__u # 3. Subtract return LaurentPolynomial_univariate(self._parent, f1 - f2, m) def degree(self): """ Return the degree of this polynomial. EXAMPLES:: sage: R. = 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 """ return self.__u.degree() + self.__n def __neg__(self): """ Return the negative of self. EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ) sage: -(1+t^5) -1 - t^5 """ return LaurentPolynomial_univariate(self._parent, -self.__u, self.__n) cpdef RingElement _mul_(self, RingElement right_r): """ EXAMPLES:: sage: R. = 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 """ cdef LaurentPolynomial_univariate right = right_r return LaurentPolynomial_univariate(self._parent, self.__u * right.__u, self.__n + right.__n) cpdef RingElement _imul_(self, RingElement right_r): """ EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ) sage: f = 1/x^3 + x + x^2 + 3*x^4 sage: g = 1 - x + x^2 - x^4 sage: f *= g; f x^-3 - x^-2 + x^-1 + 4*x^4 - 4*x^5 + 2*x^6 - 3*x^8 """ cdef LaurentPolynomial_univariate right = right_r self.__u *= right.__u self.__n += right.__n return self cpdef ModuleElement _rmul_(self, RingElement c): """ EXAMPLES:: sage: R. = 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 """ return LaurentPolynomial_univariate(self._parent, self.__u._rmul_(c), self.__n) cpdef ModuleElement _lmul_(self, RingElement c): """ EXAMPLES:: sage: R. = 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 """ return LaurentPolynomial_univariate(self._parent, self.__u._lmul_(c), self.__n) cpdef ModuleElement _ilmul_(self, RingElement c): """ EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ) sage: f = 1/x^3 + x + x^2 + 3*x^4 sage: f *= 3 """ self.__u *= c return self 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 """ cdef LaurentPolynomial_univariate self = _self right=int(r) if right != r: raise ValueError("exponent must be an integer") return LaurentPolynomial_univariate(self._parent, self.__u**right, self.__n*right) def shift(self, k): r""" Return this Laurent polynomial multiplied by the power t^n. Does not change this polynomial. EXAMPLES:: sage: R. = 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 """ return LaurentPolynomial_univariate(self._parent, self.__u, self.__n + k) def __lshift__(LaurentPolynomial_univariate self, k): """ Return the left shift of self. EXAMPLES:: sage: R. = 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 """ return LaurentPolynomial_univariate(self._parent, self.__u, self.__n + k) def __rshift__(LaurentPolynomial_univariate self, k): """ Return the right shift of self. EXAMPLES:: sage: R. = 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 """ return LaurentPolynomial_univariate(self._parent, self.__u, self.__n - k) cpdef RingElement _div_(self, RingElement right_r): """ EXAMPLES:: sage: R. = 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 (x + x^2 + 3*x^4)/(x^-7 - x + x^2 - x^4) sage: (x^-2 + x)*(x^-2 + 1) / ((x^5 + x^8)*(x + 2)) (1 + x^2)/(2*x^9 + x^10) sage: (x^-2 + x)*(x^-2 + 1) / ((x^-5 + x^-8)*(x + 2)) (x^4 + x^6)/(2 + x) """ cdef LaurentPolynomial_univariate right = right_r if right.__u.is_zero(): raise ZeroDivisionError try: return LaurentPolynomial_univariate(self._parent, self.__u / right.__u, self.__n - right.__n) except TypeError: # If that didn't work, try the fraction field return RingElement._div_(self, right) def __invert__(self): """ Return the inverse of self. EXAMPLES:: sage: R. = 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 1/(t^-2 + 2 + t^2) sage: i.parent() Fraction Field of Univariate Laurent Polynomial Ring in t over Rational Field """ if self.__u.is_constant(): return LaurentPolynomial_univariate(self._parent, ~self.__u, -self.__n) if self.__u.is_unit(): return LaurentPolynomial_univariate(self._parent, self.__u.inverse_of_unit(), -self.__n) return self._parent.one() / self def inverse_of_unit(self): """ Return the inverse of self if a unit. EXAMPLES:: sage: R. = 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 """ if self.is_unit(): return self.__invert__() raise ArithmeticError("element is not a unit") 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. = 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 """ b = self._parent(right) return LaurentPolynomial_univariate(self._parent, self.__u.gcd(b.__u), min(self.__n, b.__n)) @coerce_binop def quo_rem(self, right_r): """ Attempts to divide self by right and returns a quotient and a remainder. EXAMPLES:: sage: R. = 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) """ cdef LaurentPolynomial_univariate right = right_r q,r = self.__u.quo_rem(right.__u) ql = LaurentPolynomial_univariate(self._parent, q, self.__n - right.__n) rl = LaurentPolynomial_univariate(self._parent, r, 0) return (ql, rl) def __richcmp__(left, right, int op): """ Return the rich comparison of left and right defined by op. EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) 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 """ return (left)._richcmp(right, op) cdef int _cmp_c_impl(self, Element right_r) except -2: r""" Comparison of self and right_r. EXAMPLES:: sage: R. = 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 False :: sage: f = x^(-2) + 1 + x sage: g = x^(-1) + 2 sage: f == g False sage: f < g False sage: f > g True """ cdef LaurentPolynomial_univariate right = right_r zero = self.base_ring()(0) if not self and not right: if self.__n < right.__n: return cmp(self.__u[0], zero) elif self.__n > right.__n: return cmp(zero, right.__u[0]) # zero pad coefficients on the left, to line them up for comparison cdef long n = min(self.__n, right.__n) x = [zero] * (self.__n - n) + self.__u.list() y = [zero] * (right.__n - n) + right.__u.list() # 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) if len(x) < len(y): x.extend([zero] * (len(y) - len(x))) elif len(y) < len(x): y.extend([zero] * (len(x) - len(y))) return cmp(x,y) 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. = 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 """ return self.__n + self.__u.valuation(p) 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. = 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 """ if n <= self.valuation(): return self._parent(0) return LaurentPolynomial_univariate(self._parent, self.__u.truncate(n-self.__n), self.__n) def variable_name(self): """ Return the name of variable of self as a string. EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) sage: f = 1/x + x^2 + 3*x^4 sage: f.variable_name() 'x' """ return self._parent.variable_name() def variables(self): """ Return the tuple of variables occuring in this Laurent polynomial. EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) sage: f = 1/x + x^2 + 3*x^4 sage: f.variables() (x,) sage: R.one().variables() () """ if self.is_constant(): return () return self._parent.gens() 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. = LaurentPolynomialRing(QQ) sage: f = 1/x + x^2 + 3*x^4 sage: f.polynomial_construction() (3*x^5 + x^3 + 1, -1) """ return (self.__u, self.__n) def is_constant(self): """ Return True if self is constant. EXAMPLES:: sage: R. = 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 """ return self.__n == 0 and self.__u.is_constant() def __copy__(self): """ Return a copy of self. EXAMPLES:: sage: R. = 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 """ from copy import copy return LaurentPolynomial_univariate(self._parent, copy(self.__u), self.__n) 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 :funcderivative() function for more details. .. SEEALSO:: :meth:_derivative EXAMPLES:: sage: R. = 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. = PolynomialRing(ZZ) sage: S. = 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 """ return multi_derivative(self, args) 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. = 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. = PolynomialRing(ZZ) sage: S. = LaurentPolynomialRing(R) sage: f = 2*t/x + (3*t^2 + 6*t)*x sage: f._derivative(t) 2*x^-1 + (6*t + 6)*x """ if var is not None and var is not self._parent.gen(): # call _derivative() recursively on coefficients u = [coeff._derivative(var) for coeff in self.__u.list()] u = self._parent.polynomial_ring()(u) return LaurentPolynomial_univariate(self._parent, u, self.__n) # compute formal derivative with respect to generator if self.is_zero(): return LaurentPolynomial_univariate(self._parent, 0) cdef long m, n = self.__n a = self.__u.list() v = [(n+m)*a[m] for m from 0 <= m < len(a)] u = self._parent.polynomial_ring()(v) return LaurentPolynomial_univariate(self._parent, u, n-1) 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. = LaurentPolynomialRing(QQ) sage: f = -2*t^(-4) sage: f.integral() 2/3*t^-3 sage: f.integral().derivative() == f True """ cdef long i, n = self.__n a = self.__u.list() if self[-1] != 0: raise ArithmeticError( "the integral of is not a Laurent polynomial, since t^-1 has nonzero coefficient") if n < 0: v = [a[i]/(n+i+1) for i in range(min(-1-n,len(a)))] + [0] else: v = [] v += [a[i]/(n+i+1) for i in range(max(-n,0), len(a))] try: u = self._parent.polynomial_ring()(v) except TypeError: raise ArithmeticError("coefficients of integral cannot be coerced into the base ring") return LaurentPolynomial_univariate(self._parent, u, n+1) def __call__(self, *x): """ Compute value of this Laurent polynomial at x. EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ) sage: f = t^(-2) + t^2 sage: f(2) 17/4 sage: f(-1) 2 sage: f(1/3) 82/9 """ if isinstance(x[0], tuple): x = x[0] return self.__u(x) * (x[0]**self.__n) def factor(self): """ Return a Laurent monomial (the unit part of the factorization) and a factored polynomial. EXAMPLES:: sage: R. = 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) """ pf = self.__u.factor() u = LaurentPolynomial_univariate(self._parent, pf.unit(), self.__n) f = [] for t in pf: d = LaurentPolynomial_univariate(self._parent, t[0], 0) if d.is_unit(): u *= d**t[1] else: f.append( (d, t[1]) ) return Factorization(f, unit=u) def residue(self): """ Return the residue of self. The residue is the coefficient of t^-1. EXAMPLES:: sage: R. = 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 """ return self[-1] def constant_coefficient(self): """ Return the coefficient of the constant term of self. EXAMPLES:: sage: R. = 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 """ return self[0] cdef class LaurentPolynomial_mpair(CommutativeAlgebraElement): def __init__(self, parent, x, reduce=True): cdef class LaurentPolynomial_mpair(Commu sage: L(1/2) 1/2 """ if isinstance(x, PolyDict): if isinstance(x, LaurentPolynomial_mpair): x = x.dict() elif isinstance(x, PolyDict): x = x.dict() if isinstance(x, dict): self._mon = ETuple({},int(parent.ngens())) for k in x.keys(): # ETuple-ize keys, set _mon if not isinstance(k, (tuple, ETuple)) or len(k) != parent.ngens(): if not isinstance(k, (tuple, ETuple)) or len(k) != parent.ngens(): self._mon = ETuple({}, int(parent.ngens())) break if isinstance(k, tuple): if isinstance(k, tuple): a = x[k] del x[k] k = ETuple(k) cdef class LaurentPolynomial_mpair(Commu def _normalize(self, i = None): """ Removes the common monomials from self._poly and stores them in self._mon INPUT: - i -- an integer cdef class LaurentPolynomial_mpair(Commu EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ) sage: f = x*y + 2*y*x^2 + y sage: f.factor() #Notice the y has been factored out. 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) """ D = self._poly._mpoly_dict_recursive(self.parent().variable_names(), self.parent().base_ring()) if i is None: cdef class LaurentPolynomial_mpair(Commu if e > 0: self._poly = self._poly / self._poly.parent().gen(i) self._mon = self._mon.eadd_p(e, i) def _dict(self): """ cdef class LaurentPolynomial_mpair(Commu """ D = self._poly._mpoly_dict_recursive(self.parent().variable_names(), self.parent().base_ring()) if len(self._mon.nonzero_positions()) > 0: if len(self._mon.nonzero_positions()) > 0: DD = {} for k in D.keys(): DD[k.eadd(self._mon)] = D[k] cdef class LaurentPolynomial_mpair(Commu except AttributeError: cmpfn = None atomic = self.parent().base_ring()._repr_option('element_is_atomic') return self._prod.poly_repr(self.parent().variable_names(), return self._prod.poly_repr(self.parent().variable_names(), atomic_coefficients=atomic, cmpfn=cmpfn) def _latex_(self): cdef class LaurentPolynomial_mpair(Commu except AttributeError: cmpfn = None atomic = self.parent().base_ring()._repr_option('element_is_atomic') return self._prod.latex(self.parent().variable_names(), return self._prod.latex(self.parent().variable_names(), atomic_coefficients=atomic, cmpfn=cmpfn) def __pow__(LaurentPolynomial_mpair self, n, m): cdef class LaurentPolynomial_mpair(Commu and neither x \cdot m(x,y) nor y \cdot m(x,y) divides f(x,y). INPUT: - mon -- a monomial OUTPUT: cdef class LaurentPolynomial_mpair(Commu 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. = 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 cdef class LaurentPolynomial_mpair(Commu -7*y^2 + 5*y sage: f.coefficient(x^-2*y^2) -7 sage: f.coefficient(1) sage: f.coefficient(1) -x^6 - 7*x^-2*y^2 + 5*x^-2*y + x^-3*y^2 """ if mon.parent() is not self.parent(): cdef class LaurentPolynomial_mpair(Commu EXAMPLES:: sage: L. = 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() 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. = 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() sage: L. = 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] """ return self._poly.coefficients() cdef class LaurentPolynomial_mpair(Commu EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 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 cdef class LaurentPolynomial_mpair(Commu EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 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().iteritems())) [((3, 1, 0), 3), ((4, 0, -2), 2), ((6, -7, 0), 1), ((7, 0, -1), 4)] """ if self._prod is None: self._compute_polydict() return self._prod.dict() cpdef ModuleElement _add_(self, ModuleElement _right): """ Returns the Laurent polynomial self + right. EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ) cdef class LaurentPolynomial_mpair(Commu else: ans._poly += right._poly return ans cpdef ModuleElement _sub_(self, ModuleElement _right): """ Returns the Laurent polynomial self - right. EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ) cdef class LaurentPolynomial_mpair(Commu sage: f - g -y - z + y^-1 """ """ cdef LaurentPolynomial_mpair ans = self._new_c() cdef LaurentPolynomial_mpair right = _right cdef ETuple a, b cdef class LaurentPolynomial_mpair(Commu ans._mon = self._mon ans._poly = -self._poly return ans cpdef ModuleElement _lmul_(self, RingElement right): """ Returns self * right where right is in self's base ring. EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ) cdef class LaurentPolynomial_mpair(Commu ans._mon = self._mon ans._poly = self._poly * right return ans cpdef ModuleElement _rmul_(self, RingElement left): """ Returns left*self where left is in self's base ring. EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ) cdef class LaurentPolynomial_mpair(Commu cpdef RingElement _mul_(self, RingElement right): """ Return self*right. EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ) cdef class LaurentPolynomial_mpair(Commu def exponents(self): """ Returns a list of the exponents of self. EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ) cdef class LaurentPolynomial_mpair(Commu EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 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) cdef class LaurentPolynomial_mpair(Commu return self._poly.total_degree() + sum(self._mon) g = self.parent().gens() no_generator_found = True no_generator_found = True for i in range(len(g)): if g[i] is x: no_generator_found = False cdef class LaurentPolynomial_mpair(Commu if no_generator_found: raise TypeError, "x must be a generator of parent" return self._poly.degree(self.parent().polynomial_ring().gens()[i]) + self._mon[i] def has_inverse_of(self, i): cdef class LaurentPolynomial_mpair(Commu INPUT: - i -- The index of a generator of self.parent() OUTPUT: Returns True if self contains a monomial including the inverse of cdef class LaurentPolynomial_mpair(Commu EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 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) cdef class LaurentPolynomial_mpair(Commu EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 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 cdef class LaurentPolynomial_mpair(Commu if m < 0: return True return False def __call__(self, *x, **kwds): """ cdef class LaurentPolynomial_mpair(Commu Traceback (most recent call last): ... ZeroDivisionError TESTS:: sage: f = x + 2*y + 3*z cdef class LaurentPolynomial_mpair(Commu 6 """ n = self.parent().ngens() if len(kwds) > 0: f = self.subs(**kwds) if len(x) > 0: cdef class LaurentPolynomial_mpair(Commu return f cdef int l = len(x) if l == 1 and (PY_TYPE_CHECK(x[0], tuple) or PY_TYPE_CHECK(x[0], list)): x = x[0] l = len(x) if l != n: raise TypeError, "number of arguments does not match the number of generators in parent." cdef class LaurentPolynomial_mpair(Commu """ if in_dict is not None and kwds: raise ValueError, "you cannot specify both a dictionary and keyword arguments" g = self.parent().gens() repr_g = [repr(i) for i in g] vars = [] cdef class LaurentPolynomial_mpair(Commu term *= kwds[repr_g[i]]**mon[i] else: term *= g[i]**mon[i] out += term return out def is_univariate(self): """ Return True if this is a univariate or constant Laurent polynomial, and False otherwise. EXAMPLES:: sage: R. = 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 """ return len(self.variables()) < 2 def univariate_polynomial(self, R=None): """ Returns a univariate polynomial associated to this multivariate polynomial. INPUT: - R - (default: None) PolynomialRing 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. = 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 Rational Field 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 """ from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing v = self.variables() if len(v) > 1: raise TypeError, "polynomial must involve at most one variable" elif len(v) == 1: x = v[0] i = self._parent.gens().index(x) else: x = 'x' i = 0 #construct ring if none if R is None: R = LaurentPolynomialRing(self.base_ring(),x) return R(dict((m[i],c) for m,c in self.dict().items())) def factor(self): """ cdef class LaurentPolynomial_mpair(Commu EXAMPLES:: sage: L. = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 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) """ pf = self._poly.factor() u = self.parent(pf.unit().dict()) # self.parent won't currently take polynomials g = self.parent().gens() for i in self._mon.nonzero_positions(): u *= g[i]**self._mon[i]
• ## sage/rings/polynomial/laurent_polynomial_ring.py

diff --git a/sage/rings/polynomial/laurent_polynomial_ring.py b/sage/rings/polynomial/laurent_polynomial_ring.py
 a """ Ring of Laurent Polynomials If R is a commutative ring, then the ring of Laurent polynomials in n variables over R is R[x_1^{\pm 1}, x_2^{\pm 1}, \ldots, x_n^{\pm 1}].  We implement it as a quotient ring If R is a commutative ring, then the ring of Laurent polynomials in n variables over R is R[x_1^{\pm 1}, x_2^{\pm 1}, \ldots, x_n^{\pm 1}]. We implement it as a quotient ring .. math:: .. MATH:: R[x_1, y_1, x_2, y_2, \ldots, x_n, y_n] / (x_1 y_1 - 1, x_2 y_2 - 1, \ldots, x_n y_n - 1). from sage.structure.parent_gens import n from sage.structure.element import is_Element from sage.rings.ring import is_Ring from sage.rings.integer import Integer from sage.rings.polynomial.polynomial_ring_constructor import _single_variate as _single_variate_poly from sage.rings.polynomial.polynomial_ring_constructor import _multi_variate as _multi_variate_poly from sage.misc.latex import latex from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial_mpair from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial_mpair, LaurentPolynomial_univariate from sage.rings.ring import CommutativeRing from sage.structure.parent_gens import ParentWithGens def is_LaurentPolynomialRing(R): """ Returns True if and only if R is a Laurent polynomial ring. EXAMPLES:: sage: from sage.rings.polynomial.laurent_polynomial_ring import is_LaurentPolynomialRing def LaurentPolynomialRing(base_ring, arg named, and the other arguments must be given positionally. INPUT: - base_ring -- a commutative ring - name -- a string - names -- a list or tuple of names, or a comma separated string def LaurentPolynomialRing(base_ring, arg - sparse -- bool (default: False), whether or not elements are sparse - order -- string or :class:~sage.rings.polynomial.term_order.TermOrder, e.g., - 'degrevlex' (default) -- degree reverse lexicographic - 'lex' -- lexicographic - 'deglex' -- degree lexicographic - TermOrder('deglex',3) + TermOrder('deglex',3) -- block ordering OUTPUT: LaurentPolynomialRing(base_ring, name, sparse=False) returns a def LaurentPolynomialRing(base_ring, arg that polynomial ring. :: sage: R._assign_names(['z','w']) Traceback (most recent call last): ... ValueError: variable names cannot be changed after object creation. EXAMPLES: 1. LaurentPolynomialRing(base_ring, name, sparse=False) def LaurentPolynomialRing(base_ring, arg sage: R. = LaurentPolynomialRing(QQ) sage: (1 + w)^3 w^3 + 3*w^2 + 3*w + 1 1 + 3*w + 3*w^2 + w^3 You must specify a name:: sage: LaurentPolynomialRing(QQ) Traceback (most recent call last): ... def LaurentPolynomialRing(base_ring, arg sage: LaurentPolynomialRing(QQ, 'x') == LaurentPolynomialRing(QQ, 'y') False 2. LaurentPolynomialRing(base_ring, names,   order='degrevlex') :: sage: R = LaurentPolynomialRing(QQ, 'a,b,c'); R Multivariate Laurent Polynomial Ring in a, b, c over Rational Field def LaurentPolynomialRing(base_ring, arg All three rings are identical. :: sage: (R is S) and  (S is T) True def LaurentPolynomialRing(base_ring, arg sage: LaurentPolynomialRing(QQ, 'x', 10) Multivariate Laurent Polynomial Ring in x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 over Rational Field sage: LaurentPolynomialRing(GF(7), 'y', 5) Multivariate Laurent Polynomial Ring in y0, y1, y2, y3, y4 over Finite Field of size 7 def LaurentPolynomialRing(base_ring, arg method, all those variable names are available for interactive use:: sage: R = LaurentPolynomialRing(GF(7),15,'w'); R Multivariate Laurent Polynomial Ring in w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14 over Finite Field of size 7 Multivariate Laurent Polynomial Ring in w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14 over Finite Field of size 7 sage: R.inject_variables() Defining w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14 sage: (w0 + 2*w8 + w13)^2 def LaurentPolynomialRing(base_ring, arg n = len(names) R = _multi_variate(base_ring, names, n, sparse, order) elif isinstance(arg1, (list, tuple)): # LaurentPolynomialRing(base_ring, names (list or tuple), order='degrevlex'): # LaurentPolynomialRing(base_ring, names (list or tuple), order='degrevlex'): names = arg1 n = len(names) R = _multi_variate(base_ring, names, n, sparse, order) def _get_from_cache(key): if _cache.has_key(key): return _cache[key]   # put () here to re-enable weakrefs except TypeError, msg: raise TypeError, 'key = %s\n%s'%(key,msg) raise TypeError, 'key = %s\n%s'%(key,msg) return None def _save_in_cache(key, R): def _save_in_cache(key, R): True """ try: # We disable weakrefs since they cause segfault at the end of doctesting. # We disable weakrefs since they cause segfault at the end of doctesting. #weakref.ref(R) _cache[key] = R _cache[key] = R except TypeError, msg: raise TypeError, 'key = %s\n%s'%(key,msg) def _single_variate(base_ring, names, sp sage: _single_variate(QQ, ('x',), False) Univariate Laurent Polynomial Ring in x over Rational Field """ ############################################################ # This should later get moved to an actual single variate  # # implementation with valuation tracking,                  # # but I don't want to right now.                           # ############################################################ # We need to come up with a name for the inverse that is easy to search # for in a string *and* doesn't overlap with the name that we already have. # For now, I'm going to use a name mangling with checking method. names = normalize_names(1, names) key = (base_ring, names, sparse) P = _get_from_cache(key) def _single_variate(base_ring, names, sp prepend_string += 'k' else: break R = _multi_variate_poly(base_ring, names, 1, sparse, 'degrevlex', None) P = LaurentPolynomialRing_mpair(R, prepend_string, names) R = _single_variate_poly(base_ring, names, sparse, None) P = LaurentPolynomialRing_univariate(R, names) _save_in_cache(key, P) return P def _multi_variate(base_ring, names, n, elif isinstance(names, str): if ',' in names: names = tuple(names.split(',')) key = (base_ring, names, n, sparse, order) P = _get_from_cache(key) if P is not None: class LaurentPolynomialRing_generic(Comm self._R = R self._prepend_string = prepend_string CommutativeRing.__init__(self, R.base_ring(), names=names) self._populate_coercion_lists_(element_constructor=self._element_constructor_, self._populate_coercion_lists_(element_constructor=self._element_constructor_, init_no_parent=True) class LaurentPolynomialRing_generic(Comm """ if i < 0 or i >= self._n: raise ValueError, "generator not defined" return self(self._R.gen(i)) try: return self.__generators[i] except AttributeError: self.__generators = tuple(self(x) for x in self._R.gens()) return self.__generators[i] def is_integral_domain(self, proof = True): """ Returns True if self is an integral domain. EXAMPLES:: sage: LaurentPolynomialRing(QQ,2,'x').is_integral_domain() class LaurentPolynomialRing_generic(Comm NotImplementedError """ raise NotImplementedError def construction(self): """ Returns the construction of self. EXAMPLES:: sage: LaurentPolynomialRing(QQ,2,'x,y').construction() class LaurentPolynomialRing_generic(Comm else: return LaurentPolynomialFunctor(vars[-1], True), LaurentPolynomialRing(self.base_ring(), vars[:-1]) def completion(self, p, prec=20, extras=None): """ EXAMPLES:: sage: LaurentPolynomialRing(QQ,2,'x').completion(3) Traceback (most recent call last): ... NotImplementedError sage: P.=LaurentPolynomialRing(QQ) sage: P Univariate Laurent Polynomial Ring in x over Rational Field sage: PP=P.completion(x) sage: PP Laurent Series Ring in x over Rational Field sage: f=1-1/x sage: PP(f) -x^-1 + 1 sage: 1/PP(f) -x - x^2 - x^3 - x^4 - x^5 - x^6 - x^7 - x^8 - x^9 - x^10 - x^11 - x^12 - x^13 - x^14 - x^15 - x^16 - x^17 - x^18 - x^19 - x^20 + O(x^21) """ raise NotImplementedError if str(p) == self._names[0] and self._n == 1: from sage.rings.laurent_series_ring import LaurentSeriesRing return LaurentSeriesRing(self.base_ring(), name=self._names[0]) else: raise TypeError, "Cannot complete %s with respect to %s" % (self, p) def remove_var(self, var): """ class LaurentPolynomialRing_generic(Comm From: Multivariate Polynomial Ring in x, y over Rational Field To:   Multivariate Laurent Polynomial Ring in x, y over Rational Field """ if R is self._R: from sage.structure.coerce_maps import CallableConvertMap return CallableConvertMap(R, self, self._element_constructor_, parent_as_first_arg=False) elif isinstance(R, LaurentPolynomialRing_generic) and \ R.variable_names() == self.variable_names() and \ self.base_ring().has_coerce_map_from(R.base_ring()): return True else: f = self._R.coerce_map_from(R) if f is not None: class LaurentPolynomialRing_generic(Comm Traceback (most recent call last): ... NotImplementedError """ """ # One may eventually want ideals in these guys. raise NotImplementedError class LaurentPolynomialRing_generic(Comm sage: LaurentPolynomialRing(QQ,2,'x').term_order() Degree reverse lexicographic term order """ return self._R.term_order() class LaurentPolynomialRing_generic(Comm sage: LaurentPolynomialRing(QQ,2,'x').is_finite() False """ return False class LaurentPolynomialRing_generic(Comm def polynomial_ring(self): """ Returns the polynomial ring associated with self. EXAMPLES:: sage: LaurentPolynomialRing(QQ,2,'x').polynomial_ring() class LaurentPolynomialRing_generic(Comm base_ring = self.base_ring() if names is None: names = self.variable_names() if order is None: order = self.polynomial_ring().term_order() if self._n == 1: return LaurentPolynomialRing(base_ring, names[0], sparse = sparse) else: if order is None: order = self.polynomial_ring().term_order() return LaurentPolynomialRing(base_ring, self._n, names, order = order) class LaurentPolynomialRing_univariate(LaurentPolynomialRing_generic): def __init__(self, R, names): """ EXAMPLES:: sage: L = LaurentPolynomialRing(QQ,'x') sage: type(L) sage: L == loads(dumps(L)) True """ if R.ngens() != 1: raise ValueError("must be 1 generator") if not R.base_ring().is_integral_domain(): raise ValueError("base ring must be an integral domain") LaurentPolynomialRing_generic.__init__(self, R, '', names) def _element_constructor_(self, x): """ EXAMPLES:: sage: L = LaurentPolynomialRing(QQ, 'x') sage: L(1/2) 1/2 """ return LaurentPolynomial_univariate(self, x) def __reduce__(self): """ Used in pickling. EXAMPLES:: sage: L = LaurentPolynomialRing(QQ, 'x') sage: loads(dumps(L)) == L True """ return LaurentPolynomialRing_univariate, (self._R, self._names) class LaurentPolynomialRing_mpair(LaurentPolynomialRing_generic): def __init__(self, R, prepend_string, names): """ class LaurentPolynomialRing_mpair(Lauren 1/2 """ return LaurentPolynomial_mpair(self, x) def __reduce__(self): """ Used in pickling. EXAMPLES:: sage: L = LaurentPolynomialRing(QQ,2,'x') sage: loads(dumps(L)) == L True """ return LaurentPolynomialRing_mpair, (self._R, self._prepend_string, self._names)