Ticket #13439: trac_13439.patch

File trac_13439.patch, 16.2 KB (added by saraedum, 7 years ago)
  • sage/rings/padics/generic_nodes.py

    # HG changeset patch
    # User Julian Rueth <julian.rueth@gmail.com>
    # Date 1350933262 0
    # Node ID 7ffe38b585130075a207b9069d9f0d72c0e231d6
    # Parent  698ec14c513f99fa5a3a7aeca982cc14fd249a89
    Trac #13439: implemented (x)gcd for polynomials over padic rings and fields
    
    diff --git a/sage/rings/padics/generic_nodes.py b/sage/rings/padics/generic_nodes.py
    a b class pAdicFixedModRingGeneric(pAdicRingGeneric, FixedModGeneric): 
    411411        return self._xgcd_univariate_polynomial_fixed(f, g)
    412412
    413413class pAdicCappedAbsoluteRingGeneric(pAdicRingGeneric, CappedAbsoluteGeneric):
    414     pass
     414    def _gcd_univariate_polynomial(self, f, g):
     415        """
     416        Compute a greatest common divisor of the polynomials ``f`` and ``g``.
     417
     418        This is a helper method for
     419        :meth:`sage.rings.polynomial.polynomial_element.Polynomial.gcd`. Its
     420        implementation relies on
     421        :meth:`sage.rings.padics.padic_generic.pAdicGeneric._gcd_univariate_polynomial_fixed`
     422        which should be consulted for further details and examples.
     423
     424        INPUT:
     425
     426            - ``f``, ``g`` -- two polynomials defined over ``self``.
     427
     428        OUTPUT:
     429
     430        A polynomial defined over ``self``. The precision of the coefficients
     431        of this polynomial might be less than that of the input polynomials.
     432        (see
     433        :meth:`sage.rings.padics.padic_generic.pAdicGeneric.__xgcd_univariate_polynomial_fixed`
     434        for the precise meaning of that accuracy.)
     435
     436        AUTHORS:
     437
     438        - Julian Rueth (2012-09-05): initial version
     439
     440        EXAMPLES::
     441
     442            sage: R.<t> = ZpCA(3,20)[]
     443            sage: (t + 1).gcd( (t - 1) * (t + 1) )
     444            (1 + O(3^20))*t + (1 + O(3^20))
     445            sage: (t^3).gcd( t^5 )
     446            (1 + O(3^20))*t^3
     447
     448        Also works over extensions::
     449
     450            sage: K = ZpCA(3,20)
     451            sage: R.<a> = K[]
     452            sage: L.<a> = K.extension( a^2 - 3 ) # Eisenstein extension
     453            sage: R.<t> = L[]
     454            sage: a0,a1,a2 = 12345678+a,90123456-a,78901234*a
     455            sage: f = (t - a0) * (t - a1)^2 * (t - a2)^3
     456            sage: g = f.gcd(f.derivative())
     457            sage: g == ((t - a1) * (t - a2)^2)
     458            True
     459
     460            sage: R.<a> = K[]
     461            sage: L.<a> = K.extension( a^2 - 2 ) # unramified extension
     462            sage: R.<t> = L[]
     463            sage: a0,a1,a2 = 12345678+a,90123456-a,78901234*a
     464            sage: f = (t - a0) * (t - a1)^2 * (t - a2)^3
     465            sage: g = f.gcd(f.derivative())
     466            sage: g == ((t - a1) * (t - a2)^2)
     467            True
     468
     469        """
     470        ret, prec = self._gcd_univariate_polynomial_fixed(f, g)
     471        return ret.map_coefficients(lambda c:c.add_bigoh(prec))
     472
     473    def _xgcd_univariate_polynomial(self, f, g):
     474        """
     475        Compute a extended greatest common divisor of the polynomials ``f`` and
     476        ``g``.
     477
     478        This is a helper method for
     479        :meth:`sage.rings.polynomial.polynomial_element.Polynomial.xgcd`. Its
     480        implementation relies on
     481        :meth:`sage.rings.padics.padic_generic.pAdicGeneric._xgcd_univariate_polynomial_fixed`
     482        which should be consulted for further details and examples.
     483
     484        INPUT:
     485
     486            - ``f``, ``g`` -- two polynomials defined over ``self``.
     487
     488        OUTPUT:
     489
     490        A tuple ``r,s,t`` of polynomials defined over ``self`` such that ``r =
     491        s*f + t*g``. The precision of the coefficients of these polynomials
     492        might be less than that of the input polynomials.  (see
     493        :meth:`sage.rings.padics.padic_generic.pAdicGeneric.__xgcd_univariate_polynomial_fixed`
     494        for the precise meaning of that accuracy.)
     495
     496        AUTHORS:
     497
     498        - Julian Rueth (2012-09-05): initial version
     499
     500        EXAMPLES::
     501
     502            sage: R.<t> = ZpCA(3,20)[]
     503            sage: (t + 1).xgcd( (t - 1) * (t + 1) )
     504            ((1 + O(3^20))*t + (1 + O(3^20)), (1 + O(3^20)), 0)
     505            sage: (t^3).xgcd( t^5 )
     506            ((1 + O(3^20))*t^3, (1 + O(3^20)), 0)
     507
     508        Also works over extensions::
     509
     510            sage: K = ZpCA(3,20)
     511            sage: R.<a> = K[]
     512            sage: L.<a> = K.extension( a^2 - 3 ) # Eisenstein extension
     513            sage: R.<t> = L[]
     514            sage: a0,a1,a2 = 12345678+a,90123456-a,78901234*a
     515            sage: f = (t - a0) * (t - a1)^2 * (t - a2)^3
     516            sage: g,u,v = f.xgcd(f.derivative())
     517            sage: h = g.leading_coefficient() * ((t - a1) * (t - a2)^2)
     518            sage: g == h
     519            True
     520            sage: g == u*f + v*f.derivative()
     521            True
     522
     523            sage: R.<a> = K[]
     524            sage: L.<a> = K.extension( a^2 - 2 ) # unramified extension
     525            sage: R.<t> = L[]
     526            sage: a0,a1,a2 = 12345678+a,90123456-a,78901234*a
     527            sage: f = (t - a0) * (t - a1)^2 * (t - a2)^3
     528            sage: g,u,v = f.xgcd(f.derivative())
     529            sage: h = g.leading_coefficient() * ((t - a1) * (t - a2)^2)
     530            sage: g == h
     531            True
     532            sage: g == u*f + v*f.derivative()
     533            True
     534
     535        """
     536        r, prec, s, t = self._xgcd_univariate_polynomial_fixed(f, g)
     537        return r.map_coefficients(lambda c:c.add_bigoh(prec)), s, t
     538
    415539class pAdicCappedRelativeRingGeneric(pAdicRingGeneric, CappedRelativeRingGeneric):
    416     pass
     540    def _gcd_univariate_polynomial(self, f, g):
     541        """
     542        Compute a greatest common divisor of the polynomials ``f`` and ``g``.
     543
     544        This is a helper method for
     545        :meth:`sage.rings.polynomial.polynomial_element.Polynomial.gcd`. Its
     546        implementation relies on
     547        :meth:`sage.rings.padics.padic_generic.pAdicGeneric._gcd_univariate_polynomial_fixed`
     548        which should be consulted for further details and examples.
     549
     550        INPUT:
     551
     552            - ``f``, ``g`` -- two polynomials defined over ``self``.
     553
     554        OUTPUT:
     555
     556        A polynomial defined over ``self``. The precision of the coefficients
     557        of this polynomial might be less than that of the input polynomials.
     558        (see
     559        :meth:`sage.rings.padics.padic_generic.pAdicGeneric.__xgcd_univariate_polynomial_fixed`
     560        for the precise meaning of that accuracy.)
     561
     562        AUTHORS:
     563
     564        - Julian Rueth (2012-09-05): initial version
     565
     566        EXAMPLES::
     567
     568            sage: R.<t> = ZpCR(3,20)[]
     569            sage: (t + 1).gcd( (t - 1) * (t + 1) )
     570            (1 + O(3^20))*t + (1 + O(3^20))
     571            sage: (t^3).gcd( t^5 )
     572            (1 + O(3^20))*t^3
     573
     574        Also works over extensions::
     575
     576            sage: K = ZpCR(3,20)
     577            sage: R.<a> = K[]
     578            sage: L.<a> = K.extension( a^2 - 3 ) # Eisenstein extension
     579            sage: R.<t> = L[]
     580            sage: a0,a1,a2 = 12345678+a,90123456-a,78901234*a
     581            sage: f = (t - a0) * (t - a1)^2 * (t - a2)^3
     582            sage: g = f.gcd(f.derivative())
     583            sage: g == ((t - a1) * (t - a2)^2)
     584            True
     585
     586            sage: R.<a> = K[]
     587            sage: L.<a> = K.extension( a^2 - 2 ) # unramified extension
     588            sage: R.<t> = L[]
     589            sage: a0,a1,a2 = 12345678+a,90123456-a,78901234*a
     590            sage: f = (t - a0) * (t - a1)^2 * (t - a2)^3
     591            sage: g = f.gcd(f.derivative())
     592            sage: g == ((t - a1) * (t - a2)^2)
     593            True
     594
     595        """
     596        ret, prec = self._gcd_univariate_polynomial_fixed(f, g)
     597        return ret.map_coefficients(lambda c:c.add_bigoh(prec))
     598
     599    def _xgcd_univariate_polynomial(self, f, g):
     600        """
     601        Compute a extended greatest common divisor of the polynomials ``f`` and
     602        ``g``.
     603
     604        This is a helper method for
     605        :meth:`sage.rings.polynomial.polynomial_element.Polynomial.xgcd`. Its
     606        implementation relies on
     607        :meth:`sage.rings.padics.padic_generic.pAdicGeneric._xgcd_univariate_polynomial_fixed`
     608        which should be consulted for further details and examples.
     609
     610        INPUT:
     611
     612            - ``f``, ``g`` -- two polynomials defined over ``self``.
     613
     614        OUTPUT:
     615
     616        A tuple ``r,s,t`` of polynomials defined over ``self`` such that ``r =
     617        s*f + t*g``. The precision of the coefficients of these polynomials
     618        might be less than that of the input polynomials.  (see
     619        :meth:`sage.rings.padics.padic_generic.pAdicGeneric.__xgcd_univariate_polynomial_fixed`
     620        for the precise meaning of that accuracy.)
     621
     622        AUTHORS:
     623
     624        - Julian Rueth (2012-09-05): initial version
     625
     626        EXAMPLES::
     627
     628            sage: R.<t> = ZpCR(3,20)[]
     629            sage: (t + 1).xgcd( (t - 1) * (t + 1) )
     630            ((1 + O(3^20))*t + (1 + O(3^20)), (1 + O(3^20)), 0)
     631            sage: (t^3).xgcd( t^5 )
     632            ((1 + O(3^20))*t^3, (1 + O(3^20)), 0)
     633
     634        Also works over extensions::
     635
     636            sage: K = ZpCR(3,20)
     637            sage: R.<a> = K[]
     638            sage: L.<a> = K.extension( a^2 - 3 ) # Eisenstein extension
     639            sage: R.<t> = L[]
     640            sage: a0,a1,a2 = 12345678+a,90123456-a,78901234*a
     641            sage: f = (t - a0) * (t - a1)^2 * (t - a2)^3
     642            sage: g,u,v = f.xgcd(f.derivative())
     643            sage: h = g.leading_coefficient() * ((t - a1) * (t - a2)^2)
     644            sage: g == h
     645            True
     646            sage: g == u*f + v*f.derivative()
     647            True
     648
     649            sage: R.<a> = K[]
     650            sage: L.<a> = K.extension( a^2 - 2 ) # unramified extension
     651            sage: R.<t> = L[]
     652            sage: a0,a1,a2 = 12345678+a,90123456-a,78901234*a
     653            sage: f = (t - a0) * (t - a1)^2 * (t - a2)^3
     654            sage: g,u,v = f.xgcd(f.derivative())
     655            sage: h = g.leading_coefficient() * ((t - a1) * (t - a2)^2)
     656            sage: g == h
     657            True
     658            sage: g == u*f + v*f.derivative()
     659            True
     660
     661        """
     662        r, prec, s, t = self._xgcd_univariate_polynomial_fixed(f, g)
     663        return r.map_coefficients(lambda c:c.add_bigoh(prec)), s, t
     664
    417665class pAdicCappedRelativeFieldGeneric(pAdicFieldGeneric, CappedRelativeFieldGeneric):
    418     pass
     666    def _gcd_univariate_polynomial(self, f, g):
     667        """
     668        Compute a greatest common divisor of the polynomials ``f`` and ``g``.
     669
     670        This is a helper method for
     671        :meth:`sage.rings.polynomial.polynomial_element.Polynomial.gcd`. Its
     672        implementation relies on
     673        :meth:`sage.rings.padics.padic_generic.pAdicGeneric._gcd_univariate_polynomial_fixed`
     674        which should be consulted for further details and examples.
     675
     676        INPUT:
     677
     678            - ``f``, ``g`` -- two polynomials defined over ``self``.
     679
     680        OUTPUT:
     681
     682        A monic polynomial defined over ``self``. The precision of the
     683        coefficients of this polynomial might be less than that of the input
     684        polynomials.  (see
     685        :meth:`sage.rings.padics.padic_generic.pAdicGeneric.__xgcd_univariate_polynomial_fixed`
     686        for the precise meaning of that accuracy.)
     687
     688        AUTHORS:
     689
     690        - Julian Rueth (2012-09-05): initial version
     691
     692        EXAMPLES::
     693
     694            sage: R.<t> = QpCR(3,20)[]
     695            sage: (t + 1).gcd( (t - 1) * (t + 1) )
     696            (1 + O(3^20))*t + (1 + O(3^20))
     697            sage: (t^3).gcd( t^5 )
     698            (1 + O(3^20))*t^3
     699            sage: (t/3).gcd( t^5 )
     700            (1 + O(3^20))*t
     701
     702        Also works over extensions::
     703
     704            sage: K = QpCR(3,20)
     705            sage: R.<a> = K[]
     706            sage: L.<a> = K.extension( a^2 - 3 ) # Eisenstein extension
     707            sage: R.<t> = L[]
     708            sage: a0,a1,a2 = 12345678+~a,90123456-~a,78901234*~a
     709            sage: f = (t - a0) * (t - a1)^2 * (t - a2)^3
     710            sage: g = f.gcd(f.derivative())
     711            sage: g == ((t - a1) * (t - a2)^2)
     712            True
     713
     714            sage: R.<a> = K[]
     715            sage: L.<a> = K.extension( a^2 - 2 ) # unramified extension
     716            sage: R.<t> = L[]
     717            sage: a0,a1,a2 = 12345678+a/3,90123456-a,78901234*a/9
     718            sage: f = (t - a0) * (t - a1)^2 * (t - a2)^3
     719            sage: g = f.gcd(f.derivative())
     720            sage: g == ((t - a1) * (t - a2)^2)
     721            True
     722
     723        """
     724        # normalize f and g so that all their coefficients have non-negative valuation
     725        polys = [f,g]
     726        for i,poly in enumerate(polys):
     727            min_val = 0 if poly.is_zero() else min([c.valuation() for c in poly])
     728            polys[i] = poly.map_coefficients(lambda c:c>>min_val)
     729
     730        ret, prec = self._gcd_univariate_polynomial_fixed(*polys)
     731        if ret.is_zero(): return ret
     732        return ret.map_coefficients(lambda c:c.add_bigoh(prec)) / ret.leading_coefficient()
     733
     734    def _xgcd_univariate_polynomial(self, f, g):
     735        """
     736        Compute a extended greatest common divisor of the polynomials ``f`` and
     737        ``g``.
     738
     739        This is a helper method for
     740        :meth:`sage.rings.polynomial.polynomial_element.Polynomial.xgcd`. Its
     741        implementation relies on
     742        :meth:`sage.rings.padics.padic_generic.pAdicGeneric._xgcd_univariate_polynomial_fixed`
     743        which should be consulted for further details and examples.
     744
     745        INPUT:
     746
     747            - ``f``, ``g`` -- two polynomials defined over ``self``.
     748
     749        OUTPUT:
     750
     751        A tuple ``r,s,t`` of polynomials defined over ``self`` such that ``r =
     752        s*f + t*g`` with ``r`` monic. The precision of the coefficients of
     753        these polynomials might be less than that of the input polynomials.
     754        (see
     755        :meth:`sage.rings.padics.padic_generic.pAdicGeneric.__xgcd_univariate_polynomial_fixed`
     756        for the precise meaning of that accuracy.)
     757
     758        AUTHORS:
     759
     760        - Julian Rueth (2012-09-05): initial version
     761
     762        EXAMPLES::
     763
     764            sage: R.<t> = QpCR(3,20)[]
     765            sage: (t + 1).xgcd( (t - 1) * (t + 1) )
     766            ((1 + O(3^20))*t + (1 + O(3^20)), (1 + O(3^20)), 0)
     767            sage: (t^3).xgcd( t^5 )
     768            ((1 + O(3^20))*t^3, (1 + O(3^20)), 0)
     769
     770        Also works over extensions::
     771
     772            sage: K = ZpCR(3,20)
     773            sage: R.<a> = K[]
     774            sage: L.<a> = K.extension( a^2 - 3 ) # Eisenstein extension
     775            sage: R.<t> = L[]
     776            sage: a0,a1,a2 = 12345678+~a,90123456-~a,78901234*~a
     777            sage: f = (t - a0) * (t - a1)^2 * (t - a2)^3
     778            sage: g,u,v = f.xgcd(f.derivative())
     779            sage: h = g.leading_coefficient() * ((t - a1) * (t - a2)^2)
     780            sage: g == h
     781            True
     782            sage: g == u*f + v*f.derivative()
     783            True
     784
     785            sage: R.<a> = K[]
     786            sage: L.<a> = K.extension( a^2 - 2 ) # unramified extension
     787            sage: R.<t> = L[]
     788            sage: a0,a1,a2 = 12345678+a/3,90123456-a,78901234*a/9
     789            sage: f = (t - a0) * (t - a1)^2 * (t - a2)^3
     790            sage: g,u,v = f.xgcd(f.derivative())
     791            sage: h = g.leading_coefficient() * ((t - a1) * (t - a2)^2)
     792            sage: g == h
     793            True
     794            sage: g == u*f + v*f.derivative()
     795            True
     796
     797        TESTS:
     798
     799        Check that :trac:`13439` has been resolved::
     800
     801            sage: R.<x> = Qp(3,3)[]
     802            sage: f = 3*x + 7
     803            sage: g = 5*x + 9
     804            sage: f.xgcd(f*g)
     805            ((1 + O(3))*x + (3^-1 + 2 + O(3)), (3^-1 + O(3^2)), 0)
     806
     807            sage: R.<x> = Qp(3)[]
     808            sage: f = 490473657*x + 257392844/729
     809            sage: g = 225227399/59049*x - 8669753175
     810            sage: f.xgcd(f*g)[0] == f/f.leading_coefficient()
     811            True
     812
     813        """
     814        # normalize f and g so that all their coefficients have non-negative valuation
     815        polys = [f,g]
     816        min_vals = []
     817        for i,poly in enumerate(polys):
     818            min_val = 0 if poly.is_zero() else min([c.valuation() for c in poly])
     819            polys[i] = poly.map_coefficients(lambda c:c>>min_val)
     820            min_vals.append(min_val)
     821
     822        r, prec, s, t = self._xgcd_univariate_polynomial_fixed(*polys)
     823        # apply the shift we used for f and g to s and t
     824        s = s.map_coefficients(lambda c:c>>min_vals[0])
     825        t = t.map_coefficients(lambda c:c>>min_vals[1])
     826        if r.is_zero(): return r,s,t
     827        factor = r.leading_coefficient()
     828        return r.map_coefficients(lambda c:c.add_bigoh(prec))/factor, s/factor, t/factor
    419829
    420830class pAdicRingBaseGeneric(pAdicBaseGeneric, pAdicRingGeneric):
    421831    def construction(self):