Ticket #8972: trac-8972_fraction_of_power_series_combined.patch

File trac-8972_fraction_of_power_series_combined.patch, 37.1 KB (added by SimonKing, 11 years ago)

Replaces all previous patches

  • sage/modular/modform/find_generators.py

    # HG changeset patch
    # User Simon King <simon.king@uni-jena.de>
    # Date 1298032666 -3600
    # Node ID 354a8e5d9902e4c0bd240da9c9fe50950b963c33
    # Parent  f9f2d5576c71552ef0cc1f814d062defb663bbef
    #8972: Fractions of power series and Laurent series.
    * * *
    Fixing various errors related with inverses of power series.
    * * *
    Improving the timings after bugfixing power series and Laurent series
    * * *
    Improving timings for sqrt, further bug fixes, more doc tests.
    * * *
    Bugfix for LaurentSeries._div_
    * * *
    #8972 referee patch
    * * *
    Fixing some remaining bugs of Laurent/power series arithmetic; fixing doc tests on elliptic curves.
    
    diff --git a/sage/modular/modform/find_generators.py b/sage/modular/modform/find_generators.py
    a b  
    112112       
    113113    K = v[0].parent().base_ring()
    114114    V = K**n
    115     B = [V(g.padded_list(n)) for g in v]
     115    B = [V(g.padded_list(n) if hasattr(g,'padded_list') else g.power_series().padded_list(n)) for g in v]
    116116    if basis:
    117117        M = V.span_of_basis(B)
    118118    else:
  • sage/rings/laurent_series_ring.py

    diff --git a/sage/rings/laurent_series_ring.py b/sage/rings/laurent_series_ring.py
    a b  
    5050        sage: Frac(GF(5)['y'])
    5151        Fraction Field of Univariate Polynomial Ring in y over Finite Field of size 5
    5252   
    53     Here the fraction field is not just the Laurent series ring, so you
    54     can't use the ``Frac`` notation to make the Laurent
    55     series ring.
     53    After fixing ticket #8972, this also works if the base ring is not
     54    a field. In this case, the ``Frac`` constructor returns the Laurent
     55    series ring over the fraction field of the base ring.
    5656   
    5757    ::
    5858   
    5959        sage: Frac(ZZ[['t']])
    60         Fraction Field of Power Series Ring in t over Integer Ring
     60        Laurent Series Ring in t over Rational Field
    6161   
    6262    Laurent series rings are determined by their variable and the base
    6363    ring, and are globally unique.
     
    121121        commutative_ring.CommutativeRing.__init__(self, base_ring, names=name, category=_Fields)
    122122        self.__sparse = sparse
    123123       
     124    def one(self):
     125        from sage.all import LaurentSeries,PowerSeriesRing
     126        if self._one_element is None:
     127            B = self.base().base_ring()
     128            if hasattr(B,'ring_of_integers'):
     129                B = B.ring_of_integers()
     130            x = PowerSeriesRing(B,self.variable_name(),default_prec=self.default_prec()).one()
     131            x = LaurentSeries(self,x,check=False)
     132            self._one_element = x
     133            return x
     134        return self._one_element
     135
     136    def zero(self):
     137        from sage.all import LaurentSeries,PowerSeriesRing
     138        if self._zero_element is None:
     139            B = self.base().base_ring()
     140            if hasattr(B,'ring_of_integers'):
     141                B = B.ring_of_integers()
     142            x = PowerSeriesRing(B,self.variable_name(),default_prec=self.default_prec()).zero()
     143            x = LaurentSeries(self,x,check=False)
     144            self._zero_element = x
     145            return x
     146        return self._zero_element
     147
    124148    def base_extend(self, R):
    125149        """
    126150        Returns the laurent series ring over R in the same variable as
     
    236260                n += x._valp()
    237261                bigoh = n + x.length()
    238262                x = self(self.polynomial_ring()(x.Vec()))
    239                 return (x << n).add_bigoh(bigoh)
     263                return x.add_bigoh(bigoh-n) << n
    240264            else:  # General case, pretend to be a polynomial
    241265                return self(self.polynomial_ring()(x)) << n
    242266        elif is_FractionFieldElement(x) and \
     
    245269            x = self(x.numerator())/self(x.denominator())
    246270            return (x << n)
    247271        else:
    248             return laurent_series_ring_element.LaurentSeries(self, x, n)
     272            try:
     273                if self.power_series_ring().has_coerce_map_from(x.parent()):
     274                    if self.power_series_ring().base_ring().has_coerce_map_from(x.parent()):
     275                        return laurent_series_ring_element.LaurentSeries(self, x*self.one().power_series(internal=True), n,check=False)
     276                    if x.is_zero():
     277                        return laurent_series_ring_element.LaurentSeries(self, x, n, check=False)
     278                    v = x.valuation()
     279                    return laurent_series_ring_element.LaurentSeries(self, x>>v, v+n,check=False)
     280            except:
     281                pass
     282        return laurent_series_ring_element.LaurentSeries(self, x, n)
    249283   
    250284    def _coerce_impl(self, x):
    251285        """
  • 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 b  
    5050- Robert Bradshaw (2007-04): optimizations, shifting
    5151
    5252- Robert Bradshaw: Cython version
     53
     54- Simon King (2010-05): optimizations, some doc tests
    5355"""
    5456
    5557import operator
     
    7880    """
    7981    A Laurent Series.
    8082    """
    81        
    82     def __init__(self, parent, f, n=0):
     83    # check=False means: The user asserts that f is
     84    # a power series that coerces into the power series
     85    # ring of self and is of valuation zero.
     86    def __init__(self, parent, f, n=0,check=True):
    8387        r"""
    8488        Create the Laurent series `t^n \cdot f`. The default is
    8589        n=0.
     
    118122        """
    119123        AlgebraElement.__init__(self, parent)
    120124
     125        if not check:
     126            # the user assures that f coerces into parent.power_series_ring()
     127            # and is of valuation zero
     128            if not f:
     129                if n == infinity:
     130                    self.__n = 0
     131                    self.__u = parent.power_series_ring()(0)
     132                else:
     133                    self.__n = n
     134                    self.__u = f
     135            else:
     136                self.__n = n    # power of the variable
     137                self.__u = f    # unit part
     138            return
     139
    121140        if PY_TYPE_CHECK(f, LaurentSeries):
    122141            n += (<LaurentSeries>f).__n
    123142            if (<LaurentSeries>f).__u._parent is parent.power_series_ring():
     
    129148        ## now this is a power series, over a different ring ...
    130149        ## requires that power series rings with same vars over the
    131150        ## same parent are unique.
    132         elif parent is not f.parent():
     151        elif parent.power_series_ring() is not f.parent():
    133152            f = parent.power_series_ring()(f)           
    134153
    135154
     
    176195            sage: f = 2 + s^2 + O(s^10)
    177196            sage: f.is_unit()
    178197            False
     198
     199        Before ticket #8972, the following used to raise an error.
     200        But now, the inverse of any non-zero element exists, and
     201        the inverse is always an element of the fraction field::
     202
    179203            sage: 1/f
    180             Traceback (most recent call last):
    181             ...
    182             ArithmeticError: division not defined
     204            1/2 - 1/4*s^2 + 1/8*s^4 - 1/16*s^6 + 1/32*s^8 + O(s^10)
    183205       
    184206        ALGORITHM: A Laurent series is a unit if and only if its "unit
    185207        part" is a unit.
     
    401423        """
    402424        return iter(self.__u)
    403425
    404        
     426    def exp(self):
     427        """
     428        Return the exponential of ``self``.
     429
     430        ASSUMPTION:
     431
     432        ``self`` must in fact be a power series
     433        (non-negative valuation).
     434
     435        EXAMPLES::
     436
     437            sage: R.<t> = ZZ[[]]
     438            sage: p = t/(2+t)
     439            sage: p.exp()
     440            1 + 1/2*t - 1/8*t^2 + 1/48*t^3 + 1/384*t^4 - 19/3840*t^5 + 151/46080*t^6 - 1091/645120*t^7 + 7841/10321920*t^8 - 56519/185794560*t^9 + 396271/3715891200*t^10 - 2442439/81749606400*t^11 + 7701409/1961990553600*t^12 + 145269541/51011754393600*t^13 - 4833158329/1428329123020800*t^14 + 104056218421/42849873690624000*t^15 - 2002667085119/1371195958099968000*t^16 + 37109187217649/46620662575398912000*t^17 - 679877731030049/1678343852714360832000*t^18 + 12440309297451121/63777066403145711616000*t^19 + O(t^20)
     441            sage: q = 2/(2*t+t^3)
     442            sage: q.exp()
     443            Traceback (most recent call last):
     444            ...
     445            ArithmeticError: self is a not a power series
     446
     447        """
     448        return self.parent()(self.power_series().exp())
     449
    405450    def list(self):
    406451        """
    407452        EXAMPLES::
     
    503548        """
    504549        cdef LaurentSeries right = <LaurentSeries>right_m
    505550        cdef long m
    506        
     551
    507552        # 1. Special case when one or the other is 0.
    508553        if not right:
    509554            return self.add_bigoh(right.prec())
     
    513558        # 2. Align the unit parts.
    514559        if self.__n < right.__n:
    515560            m = self.__n
    516             f1 = self.__u
    517             f2 = right.__u << right.__n - m
     561            out = self.__u + (right.__u << right.__n - m)
    518562        elif self.__n > right.__n:
    519563            m = right.__n
    520             f1 = self.__u << self.__n - m
    521             f2 = right.__u
     564            out = (self.__u << self.__n - m) + right.__u
    522565        else:
    523566            m = self.__n
    524             f1 = self.__u
    525             f2 = right.__u
     567            out = self.__u + right.__u
    526568        # 3. Add
    527         return LaurentSeries(self._parent, f1 + f2, m)
     569        if out.is_zero():
     570            return LaurentSeries(self._parent, out, m, check=False)
     571        v = out.valuation()
     572        return LaurentSeries(self._parent, out>>v, m+v, check=False)
    528573       
    529574    cpdef ModuleElement _iadd_(self, ModuleElement right_m):
    530575        """
     
    570615        # 2. Align the unit parts.
    571616        if self.__n < right.__n:
    572617            m = self.__n
    573             f1 = self.__u
    574             f2 = right.__u << right.__n - m
     618            out = self.__u - (right.__u << right.__n - m)
     619            #f2 = right.__u << right.__n - m
    575620        else:
    576621            m = right.__n
    577             f1 = self.__u << self.__n - m
    578             f2 = right.__u
     622            out = (self.__u << self.__n - m) - right.__u
     623            #f2 = right.__u
    579624        # 3. Subtract
    580         return LaurentSeries(self._parent, f1 - f2, m)
     625        # We want to keep the parent of f1-f2 as simple as
     626        # possible. Therefore, we work a little more here,
     627        # and use the option check=False
     628        if out.is_zero():
     629            return LaurentSeries(self._parent, out, m, check=False)
     630        v = out.valuation()
     631        return LaurentSeries(self._parent, out>>v, m+v, check=False)
     632        #return LaurentSeries(self._parent, f1 - f2, m)
    581633
    582634
    583635    def add_bigoh(self, prec):
    584636        """
     637        Add ``O(t^prec)`` to ``self``.
     638
     639        INPUT:
     640
     641        prec -- integer, the precision to obtain
     642
    585643        EXAMPLES::
    586644       
    587645            sage: R.<t> = LaurentSeriesRing(QQ)
     
    589647            t^2 + t^3 + O(t^10)
    590648            sage: f.add_bigoh(5)
    591649            t^2 + t^3 + O(t^5)
     650
     651        TEST:
     652
     653            sage: P = QQ['t']
     654            sage: p = P('2+t^3+4*t^15')
     655            sage: p + O(t^10)     # indirect doctest
     656            2 + t^3 + O(t^10)
    592657        """
    593658        if prec == infinity or prec >= self.prec():
    594659            return self
    595         u = self.__u.add_bigoh(prec - self.__n)
    596         return LaurentSeries(self._parent, u, self.__n)
     660        try:
     661            u = self.__u.add_bigoh(prec - self.__n)
     662        except AttributeError: # perhaps self.__u is just a polynomial
     663            u = self.power_series().add_bigoh(prec - self.__n)
     664        return LaurentSeries(self._parent, u, self.__n,check=False)
    597665
    598666    def degree(self):
    599667        """
     
    623691            sage: -(1/(1+t+O(t^5)))
    624692            -1 + t - t^2 + t^3 - t^4 + O(t^5)
    625693        """
    626         return LaurentSeries(self._parent, -self.__u, self.__n)
     694        return LaurentSeries(self._parent, -self.__u, self.__n, check=False)
    627695
    628696    cpdef RingElement _mul_(self, RingElement right_r):
    629697        """
     
    638706        cdef LaurentSeries right = <LaurentSeries>right_r
    639707        return LaurentSeries(self._parent,
    640708                             self.__u * right.__u,
    641                              self.__n + right.__n)
     709                             self.__n + right.__n,check=False)
    642710                             
    643711    cpdef RingElement _imul_(self, RingElement right_r):
    644712        """
     
    656724        return self
    657725                             
    658726    cpdef ModuleElement _rmul_(self, RingElement c):
    659         return LaurentSeries(self._parent, self.__u._rmul_(c), self.__n)
     727        # This is incorrect, since self.__u is not necessarily
     728        # an element of self.parent.power_series_ring() (though
     729        # there is a coercion). Hence, it is not safe to call
     730        # _rmul_ directly.
     731        #return LaurentSeries(self._parent, self.__u._rmul_(c), self.__n)
     732        return LaurentSeries(self._parent, self.__u*c, self.__n)
    660733                             
    661734    cpdef ModuleElement _lmul_(self, RingElement c):
    662         return LaurentSeries(self._parent, self.__u._lmul_(c), self.__n)
     735        #return LaurentSeries(self._parent, self.__u._lmul_(c), self.__n)
     736        return LaurentSeries(self._parent, c*self.__u, self.__n)
    663737                             
    664738    cpdef ModuleElement _ilmul_(self, RingElement c):
    665739        self.__u *= c
     
    681755        right=int(r)
    682756        if right != r:
    683757            raise ValueError, "exponent must be an integer"
    684         return LaurentSeries(self._parent, self.__u**right, self.__n*right)
     758        return LaurentSeries(self._parent, self.__u**right, self.__n*right,check=False)
    685759       
    686760    def shift(self, k):
    687761        r"""
     
    714788
    715789        - Robert Bradshaw (2007-04-18)
    716790        """
    717         return LaurentSeries(self._parent, self.__u, self.__n + k)       
     791        return LaurentSeries(self._parent, self.__u, self.__n + k,check=False)
    718792       
    719793    def __lshift__(LaurentSeries self, k):
    720         return LaurentSeries(self._parent, self.__u, self.__n + k)
     794        """
     795        Despite the fact that higher order terms are printed to the
     796        right in a power series, left shifting increases the powers
     797        of `t`. This is to be consistent with polynomials, integers,
     798        etc.
     799
     800        TEST::
     801
     802            sage: R.<t> = LaurentSeriesRing(QQ['y'])
     803            sage: f = (t+t^-1)^4; f
     804            t^-4 + 4*t^-2 + 6 + 4*t^2 + t^4
     805            sage: (f + O(t^5)) << 2
     806            t^-2 + 4 + 6*t^2 + 4*t^4 + t^6 + O(t^7)
     807
     808        """
     809        return LaurentSeries(self._parent, self.__u, self.__n + k,check=False)
    721810
    722811    def __rshift__(LaurentSeries self, k):
    723         return LaurentSeries(self._parent, self.__u, self.__n - k)
     812        """
     813        Despite the fact that higher order terms are printed to the
     814        right in a power series, right shifting decreases the powers
     815        of `t`. This is to be consistent with polynomials, integers,
     816        etc.
     817
     818        TEST::
     819
     820            sage: R.<t> = LaurentSeriesRing(QQ['y'])
     821            sage: f = (t+t^-1)^4; f
     822            t^-4 + 4*t^-2 + 6 + 4*t^2 + t^4
     823            sage: f >> 3
     824            t^-7 + 4*t^-5 + 6*t^-3 + 4*t^-1 + t
     825            sage: (f + O(t^5)) >> 2
     826            t^-6 + 4*t^-4 + 6*t^-2 + 4 + t^2 + O(t^3)
     827            sage: (f + O(t^2)) >> 5
     828            t^-9 + 4*t^-7 + 6*t^-5 + O(t^-3)
     829
     830        """
     831        return LaurentSeries(self._parent, self.__u, self.__n - k,check=False)
    724832       
    725833    def truncate(self, long n):
    726834        r"""
    727835        Returns the laurent series of degree ` < n` which is
    728836        equivalent to self modulo `x^n`.
     837
     838        EXAMPLE::
     839
     840            sage: R.<I> = ZZ[[]]
     841            sage: f = (1-I)/(1+I+O(I^8)); f
     842            1 - 2*I + 2*I^2 - 2*I^3 + 2*I^4 - 2*I^5 + 2*I^6 - 2*I^7 + O(I^8)
     843            sage: f.truncate(5)
     844            1 - 2*I + 2*I^2 - 2*I^3 + 2*I^4 + O(I^5)
     845
    729846        """
    730847        if n <= self.__n:
    731848            return LaurentSeries(self._parent, 0)
    732849        else:
    733             return LaurentSeries(self._parent, self.__u.truncate_powerseries(n - self.__n), self.__n)
     850            return LaurentSeries(self._parent, self.__u.truncate_powerseries(n - self.__n), self.__n,check=False)
    734851           
    735852    def truncate_neg(self, long n):
    736853        r"""
     
    739856       
    740857        This is equivalent to
    741858        ```self - self.truncate(n)```.
     859
     860        EXAMPLE::
     861
     862            sage: R.<I> = ZZ[[]]
     863            sage: f = (1-I)/(1+I+O(I^8)); f
     864            1 - 2*I + 2*I^2 - 2*I^3 + 2*I^4 - 2*I^5 + 2*I^6 - 2*I^7 + O(I^8)
     865            sage: f.truncate_neg(5)
     866            -2*I^5 + 2*I^6 - 2*I^7 + O(I^8)
     867
    742868        """
    743         return LaurentSeries(self._parent, self.__u >> (n - self.__n), n)
     869        return LaurentSeries(self._parent, self.__u >> (n - self.__n), n,check=False)
    744870       
    745871    cpdef RingElement _div_(self, RingElement right_r):
    746872        """
     
    753879            1 + x + 3*x^3 + O(x^6)
    754880            sage: f/g
    755881            x^8 + x^9 + 3*x^11 + O(x^14)
     882
     883        TEST:
     884
     885        The following was fixed in ticket #8972::
     886
     887            sage: L.<x> = LaurentSeriesRing(ZZ)
     888            sage: 1/(2+x)
     889            1/2 - 1/4*x + 1/8*x^2 - 1/16*x^3 + 1/32*x^4 - 1/64*x^5 + 1/128*x^6 - 1/256*x^7 + 1/512*x^8 - 1/1024*x^9 + 1/2048*x^10 - 1/4096*x^11 + 1/8192*x^12 - 1/16384*x^13 + 1/32768*x^14 - 1/65536*x^15 + 1/131072*x^16 - 1/262144*x^17 + 1/524288*x^18 - 1/1048576*x^19 + O(x^20)
     890
     891            sage: R.<x> = ZZ[[]]
     892            sage: y = (3*x+2)/(1+x)
     893            sage: y/x
     894            2*x^-1 + 1 - 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 + O(x^19)
     895
    756896        """
    757897        cdef LaurentSeries right = <LaurentSeries>right_r
     898        cdef LaurentSeries out
    758899        if right.__u.is_zero():
    759900            raise ZeroDivisionError
    760901        try:
    761             return LaurentSeries(self._parent,
    762                              self.__u / right.__u,
    763                              self.__n - right.__n)
     902            inv = ~self._parent.power_series_ring()(right.__u)
     903            new_base = inv.parent().base()
     904            old_base = self._parent.base()
     905            if (new_base is old_base) or old_base.has_coerce_map_from(new_base):
     906                return LaurentSeries(self._parent, self.__u * inv, self.__n - right.__n, check=False)
     907            # need to go to the fraction field
     908            return LaurentSeries(self._parent.base_extend(new_base), self.__u.base_extend(new_base) * inv, self.__n - right.__n, check=False)
    764909        except TypeError, msg:
    765             # todo: this could also make something in the formal fraction field.
    766910            raise ArithmeticError, "division not defined"
    767911
    768912
     
    9511095        return self.__u.prec() + self.__n
    9521096
    9531097    def __copy__(self):
    954         return LaurentSeries(self._parent, self.__u.copy(), self.__n)
     1098        return LaurentSeries(self._parent, self.__u.copy(), self.__n, check=False)
    9551099
    9561100
    9571101    def derivative(self, *args):
     
    10991243        return LaurentSeries(self._parent, u, n+1)
    11001244
    11011245
    1102     def power_series(self):
     1246    def power_series(self, internal=False):
    11031247        """
     1248        If ``self`` is of non-negative valuation, return the underlying power series
     1249
     1250        INPUT:
     1251
     1252        - ``internal`` (optional bool, default ``False``): Return the power series
     1253          as it is stored internally; with this option, the result might be over a
     1254          base ring that is different from the base ring of the Laurent series ring.
     1255
     1256        OUTPUT:
     1257
     1258        - a power series, or an ``ArithmeticError`` if the valuation is negative.
     1259
    11041260        EXAMPLES::
    11051261       
    11061262            sage: R.<t> = LaurentSeriesRing(ZZ)
     
    11151271            Traceback (most recent call last):
    11161272            ...
    11171273            ArithmeticError: self is a not a power series
     1274
     1275        TEST:
     1276
     1277        Since ticket #8972, the fraction field of a power series ring is
     1278        a Laurent series ring over the fraction field of the base ring::
     1279
     1280            sage: P.<t> = ZZ[[]]
     1281            sage: F = Frac(P); F
     1282            Laurent Series Ring in t over Rational Field
     1283
     1284        Although internally ``1/(1+t)`` is stored as a power series over
     1285        the integers in order to speed up computations, the power series
     1286        returned by this method is over the rationals::
     1287
     1288            sage: g = 1/(1+t); g
     1289            1 - t + t^2 - t^3 + t^4 - t^5 + t^6 - t^7 + t^8 - t^9 + t^10 - t^11 + t^12 - t^13 + t^14 - t^15 + t^16 - t^17 + t^18 - t^19 + O(t^20)
     1290            sage: g.power_series().parent()
     1291            Power Series Ring in t over Rational Field
     1292            sage: g.power_series(internal=True).parent()
     1293            Power Series Ring in t over Integer Ring
     1294
    11181295        """
    11191296        if self.__n < 0:
    11201297            raise ArithmeticError, "self is a not a power series"
    11211298        u = self.__u
    11221299        t = u.parent().gen()
    1123         return t**(self.__n) * u
     1300        if internal:
     1301            return t**(self.__n) * u
     1302        return self._parent.power_series_ring()(t**(self.__n) * u)
    11241303       
    11251304    def __call__(self, *x):
    11261305        """
     
    11431322
    11441323
    11451324def make_element_from_parent(parent, *args):
     1325    """
     1326    An auxiliary function, that makes an element of a given parent structure
     1327
     1328    INPUT:
     1329
     1330    - ``parent``, a parent structure
     1331    - some further arguments
     1332
     1333    OUTPUT:
     1334
     1335    ``parent`` is called with the given arguments
     1336
     1337    EXAMPLE::
     1338
     1339        sage: from sage.rings.laurent_series_ring_element import make_element_from_parent
     1340        sage: P.<t> = ZZ[[]]
     1341        sage: F = Frac(P)
     1342        sage: make_element_from_parent(P,[1,2,3])
     1343        1 + 2*t + 3*t^2
     1344        sage: make_element_from_parent(P,[1,2,3],5)
     1345        1 + 2*t + 3*t^2 + O(t^5)
     1346        sage: make_element_from_parent(F,[1,2,3],-4)
     1347        t^-4 + 2*t^-3 + 3*t^-2
     1348
     1349    """
    11461350    return parent(*args)
  • sage/rings/power_series_poly.pyx

    diff --git a/sage/rings/power_series_poly.pyx b/sage/rings/power_series_poly.pyx
    a b  
    585585        EXAMPLES::
    586586       
    587587            sage: R.<I> = GF(2)[[]]
    588             sage: f = 1/(1+I+O(I^8)); f
     588            sage: f = (1/(1+I+O(I^8))).power_series(); f
    589589            1 + I + I^2 + I^3 + I^4 + I^5 + I^6 + I^7 + O(I^8)
    590590            sage: f.truncate(5)
    591591            I^4 + I^3 + I^2 + I + 1
     
    616616        EXAMPLES::
    617617       
    618618            sage: R.<I> = GF(2)[[]]
    619             sage: f = 1/(1+I+O(I^8)); f
     619            sage: f = (1/(1+I+O(I^8))).power_series(); f
    620620            1 + I + I^2 + I^3 + I^4 + I^5 + I^6 + I^7 + O(I^8)
    621621            sage: f.truncate_powerseries(5)
    622622            1 + I + I^2 + I^3 + I^4 + O(I^5)
     
    841841            ...
    842842            ValueError: Series must have valuation one for reversion.
    843843
    844 
    845 
    846844        """
    847845        if self.valuation() != 1:
    848846            raise ValueError("Series must have valuation one for reversion.")
     
    893891        t = f.parent().gen()
    894892        R = f.parent().base_ring()
    895893
    896         h = t/f
     894        # Since trac ticket #8972, t/f is not a power series but a Laurent
     895        # polynomial. Hence, for getting the padded list, we first need
     896        # to get the power series out of it
     897        h = (t/f).power_series()
    897898        k = 1
    898899        g = 0
    899900        for i in range(1, out_prec):
  • sage/rings/power_series_ring.py

    diff --git a/sage/rings/power_series_ring.py b/sage/rings/power_series_ring.py
    a b  
    9494
    9595- Niles Johnson (2010-09): implement multivariate power series
    9696
     97- Simon King (2010-05): make fraction_field be a cached method; conversion
     98  of a Laurent series of non-negative valuation into a power series.
     99
    97100TESTS::
    98101
    99102    sage: R.<t> = PowerSeriesRing(QQ)
     
    618621            sage: R(x + x^2 + x^3 + x^5, 3)
    619622            t + t^2 + O(t^3)
    620623        """
     624        try:
     625            f = f.power_series()
     626        except:
     627            pass
    621628        if isinstance(f, power_series_ring_element.PowerSeries) and f.parent() is self:
    622629            if prec >= f.prec():
    623630                return f
     
    644651        from sage.categories.pushout import CompletionFunctor
    645652        return CompletionFunctor(self._names[0], self.default_prec()),  self._poly_ring()
    646653
     654    def is_integral_domain(self, **kwds):
     655        return self.base().is_integral_domain(**kwds)
     656
     657    def fraction_field(self):
     658        """
     659        Return the fraction field of this power series ring, which
     660        is the same as the Laurent series ring over the fraction
     661        field of the base ring of ``self``.
     662
     663        EXAMPLE::
     664
     665            sage: R.<x> = ZZ.quo(53)[[]]
     666            sage: FractionField(R)
     667            Laurent Series Ring in x over Ring of integers modulo 53
     668            sage: 1/x in FractionField(R)
     669            True
     670        """
     671        from sage.all import LaurentSeriesRing
     672        return LaurentSeriesRing(self.base().fraction_field(),self.variable_names())
     673
    647674    def _coerce_impl(self, x):
    648675        """
    649676        Return canonical coercion of x into self.
     
    957984            sage: S.<s> = PowerSeriesRing(ZZ)
    958985            sage: s in R
    959986            False
     987
     988        TEST:
     989
     990        The following was fixed in ticket #8972. If a Laurent
     991        series is in fact a power series that can be interpreted
     992        in ``self`` then it is considered an element of ``self``::
     993
     994            sage: R.<x> = ZZ[[]]
     995            sage: y = (1+x)/(1-4*x)
     996            sage: y in R
     997            True
     998            sage: y.parent()
     999            Laurent Series Ring in x over Rational Field
     1000            sage: (1+x)/(2-x) in R
     1001            False
     1002            sage: 2/2 in R
     1003            True
     1004
    9601005        """
    9611006        if x.parent() == self:
    9621007            return True
     1008        # first case: x coerces into self
    9631009        try:
    9641010            self._coerce_(x)
     1011            return True
    9651012        except TypeError:
     1013            pass
     1014        # second case: x is a (ducktyped) Laurent series of non-negative valuation
     1015        try:
     1016            self(x.power_series())
     1017            return True
     1018        except (TypeError,AttributeError,ArithmeticError):
     1019            pass
     1020        # third case: x is anything else that can be interpreted in self
     1021        try:
     1022            self.fraction_field()._coerce_(x)
     1023            self(x)
     1024            return True
     1025        except:
    9661026            return False
    967         return True
    9681027
    9691028    def is_atomic_repr(self):
    9701029        """
     
    10291088                                                 self.base_ring(), self.variable_name(), sparse=self.is_sparse())
    10301089            return self.__laurent_series_ring           
    10311090   
     1091from sage.misc.cachefunc import cached_method
    10321092class PowerSeriesRing_domain(PowerSeriesRing_generic, integral_domain.IntegralDomain):
    1033       pass
    1034    
     1093    @cached_method
     1094    def fraction_field(self):
     1095        """
     1096        Return the fraction field of this power series ring, which
     1097        is the same as the Laurent series ring over the fraction
     1098        field of the base ring of ``self``.
     1099
     1100        EXAMPLE::
     1101
     1102            sage: R1.<x> = ZZ[[]]
     1103            sage: FractionField(R1)
     1104            Laurent Series Ring in x over Rational Field
     1105            sage: R2.<x> = GF(3)['t'][[]]
     1106            sage: 1/x in FractionField(R2)
     1107            True
     1108        """
     1109        from sage.all import LaurentSeriesRing
     1110        return LaurentSeriesRing(self.base().fraction_field(),self.variable_names()) #self.laurent_series_ring().base_extend(self.base().fraction_field())
     1111
    10351112class PowerSeriesRing_over_field(PowerSeriesRing_domain):
     1113    @cached_method
    10361114    def fraction_field(self):
    10371115        """
    10381116        Return the fraction field of this power series ring, which is
  • sage/rings/power_series_ring_element.pyx

    diff --git a/sage/rings/power_series_ring_element.pyx b/sage/rings/power_series_ring_element.pyx
    a b  
    1414
    1515- Robert Bradshaw (2007-04): Cython version
    1616
     17- Simon King (2010-05): optimizations; quotients of power series are *always* Laurent series
     18
    1719EXAMPLE::
    1820
    1921    sage: R.<x> = PowerSeriesRing(ZZ)
     
    617619            sage: f = 1/(1+I+O(I^8)); f
    618620            1 + I + I^2 + I^3 + I^4 + I^5 + I^6 + I^7 + O(I^8)
    619621            sage: f.truncate(5)
    620             I^4 + I^3 + I^2 + I + 1
     622            1 + I + I^2 + I^3 + I^4 + O(I^5)
    621623        """
    622624        if prec is infinity:
    623625            prec = self._prec
     
    796798   
    797799    def __invert__(self):
    798800        """
    799         Inverse of the power series (i.e. a series Y such that XY = 1). The
    800         first nonzero coefficient must be a unit in the coefficient ring.
     801        Inverse of the power series (i.e. a series Y such that XY = 1).
    801802        If the valuation of the series is positive, this function will
    802         return a Laurent series.
     803        return a Laurent series, otherwise it returns a power series.
     804        If the first coefficient is a unit then the base ring of the
     805        output is the same as the base ring of ``self``; otherwise, it
     806        is the fraction field.
    803807       
    804808        ALGORITHM: Uses Newton's method. Complexity is around
    805809        `O(M(n) \log n)`, where `n` is the precision and
     
    838842        ::
    839843       
    840844            sage: 1/(2 + q)
    841              1/2 - 1/4*q + 1/8*q^2 - 1/16*q^3 + 1/32*q^4 + O(q^5)
     845            1/2 - 1/4*q + 1/8*q^2 - 1/16*q^3 + 1/32*q^4 + O(q^5)
    842846       
    843847        ::
    844848       
     
    858862            1/17 - 3/289*t^2 + 9/4913*t^4 - 27/83521*t^6 + 81/1419857*t^8 - 1587142/24137569*t^10 + O(t^12)
    859863            sage: u*v
    860864            1 + O(t^12)
    861        
     865
     866        TEST:
     867
     868        The following was fixed in ticket #8972::
     869
     870            sage: P.<t> = ZZ[[]]
     871            sage: 1 / (2+t)
     872            1/2 - 1/4*t + 1/8*t^2 - 1/16*t^3 + 1/32*t^4 - 1/64*t^5 + 1/128*t^6 - 1/256*t^7 + 1/512*t^8 - 1/1024*t^9 + 1/2048*t^10 - 1/4096*t^11 + 1/8192*t^12 - 1/16384*t^13 + 1/32768*t^14 - 1/65536*t^15 + 1/131072*t^16 - 1/262144*t^17 + 1/524288*t^18 - 1/1048576*t^19 + O(t^20)
     873
    862874        AUTHORS:
    863875
    864876        - David Harvey (2006-09-09): changed to use Newton's method
     877        - Simon King (2010-05): change to the fraction field of the coefficient ring, if necessary.
    865878        """
    866879        if self == 1:
    867880            return self
    868881        prec = self.prec()
    869882        if prec is infinity and self.degree() > 0:
    870883            prec = self._parent.default_prec()
    871         if self.valuation() > 0:
    872             u = ~self.valuation_zero_part()    # inverse of unit part
    873             R = self._parent.laurent_series_ring()
    874             return R(u, -self.valuation())
     884        v = self.valuation()
     885        if v > 0:
     886            try:
     887                u = ~(self>>v)    # inverse of unit part
     888            except:
     889                u = ~((self>>v)*self._parent.base().fraction_field()(1))
     890            try:
     891                R = self._parent.fraction_field()
     892            except TypeError: # no integral domain
     893                R = self._parent.laurent_series_ring()
     894            from sage.all import LaurentSeries
     895            return LaurentSeries(R,u,-v,check=False)# R(u, -self.valuation())
    875896
    876897        # Use Newton's method, i.e. start with single term approximation,
    877898        # and then iteratively compute $x' = 2x - Ax^2$, where $A$ is the
     
    887908
    888909        A = self.truncate()
    889910        R = A.parent()     # R is the corresponding polynomial ring
    890         current = R(first_coeff)
     911        try:
     912            current = R(first_coeff)
     913            fracfield = False
     914        except TypeError:
     915            fracfield = True
     916            R = R.base_extend(R.base().fraction_field())
     917            current = R(first_coeff)
    891918
    892919        # todo: in the case that the underlying polynomial ring is
    893920        # implemented via NTL, the truncate() method should use NTL's
     
    901928            z = current.square() * A.truncate(next_prec)
    902929            current = 2*current - z.truncate(next_prec)
    903930
    904         return self._parent(current, prec=prec)
     931        if not fracfield:
     932            return self._parent(current, prec=prec)
     933        return self._parent.base_extend(R.base())(current, prec=prec)
    905934
    906935        # Here is the old code, which uses a simple recursion, and is
    907936        # asymptotically inferior:
     
    9761005            t + O(t^21)
    9771006            sage: (t^5/(t^2 - 2)) * (t^2 -2 )
    9781007            t^5 + O(t^25)
     1008
     1009        TEST:
     1010
     1011        The following tests against bugs that were fixed in
     1012        ticket #8972::
     1013
     1014            sage: P.<t> = ZZ[]
     1015            sage: R.<x> = P[[]]
     1016            sage: 1/(t*x)
     1017            1/t*x^-1
     1018            sage: R.<t> = PowerSeriesRing(ZZ.quo(15))
     1019            sage: t/(1+t)
     1020            t + 14*t^2 + t^3 + 14*t^4 + t^5 + 14*t^6 + t^7 + 14*t^8 + t^9 + 14*t^10 + t^11 + 14*t^12 + t^13 + 14*t^14 + t^15 + 14*t^16 + t^17 + 14*t^18 + t^19 + 14*t^20 + O(t^21)
     1021            sage: t/(3+t)
     1022            Traceback (most recent call last):
     1023            ...
     1024            ZeroDivisionError: Inverse does not exist.
     1025
    9791026        """
    9801027        denom = <PowerSeries>denom_r
    9811028        if denom.is_zero():
    9821029            raise ZeroDivisionError, "Can't divide by something indistinguishable from 0"
    983         u = denom.valuation_zero_part()
    984         inv = ~u  # inverse
    985        
    986         v = denom.valuation()
    987         if v > self.valuation():
    988             R = self._parent.laurent_series_ring()
    989             return R(self)/R(denom)
    990        
     1030        try:
     1031            F = self._parent.fraction_field()
     1032        except:
     1033            # Inverses may not always exist. So, we try,
     1034            # and if the result exists, it will be in the
     1035            # parent of self.
     1036            return self* ~denom
    9911037        # Algorithm: Cancel common factors of q from top and bottom,
    9921038        # then invert the denominator.  We do the cancellation first
    9931039        # because we can only invert a unit (and remain in the ring
    994         # of power series).
    995        
    996         if v > 0:
    997             num = self >> v
    998         else:
    999             num = self
    1000         return num*inv
     1040        # of power series).       
     1041        from sage.all import LaurentSeries
     1042        if self.is_zero():
     1043            return F.zero_element()
     1044        v = denom.valuation()
     1045        w = self.valuation()
     1046        u = denom>>v#denom.valuation_zero_part()
     1047        try:
     1048            inv = ~u
     1049        except: # need to change to the fraction field of the base
     1050            inv = ~(u*F.base().one())
     1051        return LaurentSeries(F,(self>>w)*inv,w-v,check=False)
    10011052
    10021053    def __mod__(self, other):
    10031054        """
     
    11861237        - Robert Bradshaw
    11871238
    11881239        - William Stein
     1240
    11891241        """
    11901242        if self.is_zero():
    11911243            ans = self._parent(0).O(self.prec()/2)
     
    12571309        s = a.parent()([s])
    12581310        for cur_prec in sage.misc.misc.newton_method_sizes(prec)[1:]:
    12591311            (<PowerSeries>s)._prec = cur_prec
    1260             s = half * (s + a/s)
     1312            s = half * (s + (a * ~s))
    12611313       
    12621314        ans = s
    12631315        if val != 0:
  • sage/schemes/elliptic_curves/ell_wp.py

    diff --git a/sage/schemes/elliptic_curves/ell_wp.py b/sage/schemes/elliptic_curves/ell_wp.py
    a b  
    321321        True
    322322
    323323    """
    324     a_recip = 1/a
     324    a_recip = ~a # 1/a
    325325    B =  b * a_recip
    326326    C =  c * a_recip
    327327    int_B = B.integral()
    328328    J = int_B.exp()
    329     J_recip = 1/J
     329    J_recip = ~J # 1/J
    330330    CJ = C * J
    331331    int_CJ = CJ.integral()
    332332    f =  J_recip * (alpha + int_CJ)
  • sage/schemes/elliptic_curves/formal_group.py

    diff --git a/sage/schemes/elliptic_curves/formal_group.py b/sage/schemes/elliptic_curves/formal_group.py
    a b  
    300300            return y + O(t**prec)
    301301        w = self.w(prec+6) # XXX why 6?
    302302        t = w.parent().gen()
    303         y = -(w**(-1)) + O(t**prec)
     303        y = O(t**prec) - (~w)
     304        #y = -(w**(-1)) + O(t**prec)
    304305        self.__y = (prec, y)
    305306        return self.__y[1]
    306307
  • sage/schemes/elliptic_curves/padics.py

    diff --git a/sage/schemes/elliptic_curves/padics.py b/sage/schemes/elliptic_curves/padics.py
    a b  
    16331633        ...         g = [R.random_element() for i in range(N)]
    16341634        ...         g[0] = R(1)
    16351635        ...         g = Rx(g, len(g))
    1636         ...         f = g.derivative() / g
     1636        ...         f = g.derivative() * ~g
    16371637        ...         # perturb f by something whose integral is in I
    16381638        ...         err = [R.random_element() * p**(N-i) for i in range(N+1)]
    16391639        ...         err = Rx(err, len(err))
     
    16611661        G = Rx(G.list(), s)
    16621662       
    16631663        # extend current approximation to be correct to s terms
    1664         H = G.derivative() / G - F
     1664        H = G.derivative() * ~G - F# / G - F
    16651665        # Do the integral of H over QQ[x] to avoid division by p problems
    16661666        H = Rx(Qx(H).integral())
    16671667        G = G * (1 - H)
  • sage/structure/element.pyx

    diff --git a/sage/structure/element.pyx b/sage/structure/element.pyx
    a b  
    18101810                raise ZeroDivisionError, "Cannot divide by zero"
    18111811            else:
    18121812                raise TypeError, arith_error_message(self, right, div)
     1813        except TypeError:
     1814            try:
     1815                if self._parent.fraction_field() is not self._parent:
     1816                    return self._parent.fraction_field()(self)/self._parent.fraction_field()(right)
     1817                else:
     1818                    raise RuntimeError
     1819            except:
     1820                if not right:
     1821                    raise ZeroDivisionError, "Cannot divide by zero"
     1822                else:
     1823                    raise TypeError, arith_error_message(self, right, div)
     1824
    18131825
    18141826    def __idiv__(self, right):
    18151827        """