Ticket #2329: trac-2329.patch

File trac-2329.patch, 12.7 KB (added by craigcitro, 14 years ago)
  • sage/libs/pari/gen.pxd

    # HG changeset patch
    # User Craig Citro <craigcitro@gmail.com>
    # Date 1204102375 28800
    # Node ID 5858861920416cf6360f8fac386883675661a9ab
    # Parent  59538ebc8f3bc9e36d8e847c5c15a8cad5a90791
    Add interface to Pari's rnfisnorm.
    
    diff -r 59538ebc8f3b -r 585886192041 sage/libs/pari/gen.pxd
    a b cdef class gen(sage.structure.element.Ri 
    1212    cdef gen new_gen_noclear(self, GEN x)
    1313    cdef gen pari(self, object x)
    1414    cdef GEN _deepcopy_to_python_heap(self, GEN x, pari_sp* address)
    15     cdef int get_var(self, v)   
     15    cdef int get_var(self, v)
     16    cpdef gen getattr(self, attr)
    1617
    1718cimport sage.structure.parent_base
    1819
  • sage/libs/pari/gen.pyx

    diff -r 59538ebc8f3b -r 585886192041 sage/libs/pari/gen.pyx
    a b cdef class gen(sage.structure.element.Ri 
    326326    ###########################################
    327327    # ACCESS
    328328    ###########################################
    329     #def __getattr__(self, attr):
    330     def getattr(self, attr):
     329   
     330    cpdef gen getattr(self, attr):
     331        """
     332        Return attribute attr of self. This is equivalent to
     333        self.attr in Pari.
     334
     335        EXAMPLES:
     336            sage: K.<t> = NumberField(x**3-2) ; K_pari = K.pari_nf()
     337            sage: K_pari.getattr('zk')
     338            [1, x, x^2]
     339            sage: pari('K = nfinit(x^3-2); K.zk')
     340            [1, x, x^2]
     341            sage: Integers(7)(3)._pari_()
     342            Mod(3, 7)
     343            sage: Integers(7)(3)._pari_().getattr('mod')
     344            7
     345        """
    331346        t0GEN(str(self) + '.' + str(attr))
    332347        return self.new_gen(t0)
    333348
    334     def __getitem__(gen self, n):
     349    def __getitem__(self, n):
    335350        """
    336351        Return the nth entry of self. The indexing is 0-based, like
    337352        in Python. Note that this is *different* than the default
    cdef class gen(sage.structure.element.Ri 
    398413            TypeError: unindexable object
    399414            sage: m = pari("[[1,2;3,4],5]") ; m[0][1,0]
    400415            3
     416            sage: m = pari("Mod(238,92387)") ; m[0]
     417            238
     418            sage: m[1]
     419            92387
     420            sage: pari("Mod(x,x^2-3)")[1].type()
     421            't_POL'
     422            sage: pari("Mod(1,x^2-3)")[0].type()
     423            't_INT'
    401424        """
    402425        cdef int pari_type
    403426
    cdef class gen(sage.structure.element.Ri 
    448471        elif n < 0 or n >= glength(self.g):
    449472            raise IndexError, "index out of bounds"
    450473       
    451         elif typ(self.g) == t_VEC or typ(self.g) == t_MAT:
     474        elif pari_type == t_VEC or pari_type == t_MAT:
    452475            if PyDict_Contains(self._refers_to, n):
    453476                return self._refers_to[n]
    454477            else:
    cdef class gen(sage.structure.element.Ri 
    460483                self._refers_to[n] = val
    461484                return val
    462485
    463         elif typ(self.g) == t_VECSMALL:
     486        elif pari_type == t_VECSMALL:
    464487            return self.g[n+1]
    465488
    466         elif typ(self.g) == t_STR:
     489        elif pari_type == t_STR:
    467490            return chr( (<char *>(self.g+1))[n] )
    468491       
    469         elif typ(self.g) == t_LIST:
     492        elif pari_type == t_LIST:
    470493            return P.new_ref(gel(self.g,n+2), self)
    471494
    472495        elif pari_type in (t_INTMOD, t_POLMOD):
    473             # if we keep going we would get:
    474             #   [0] = modulus
    475             #   [1] = lift to t_INT or t_POL
    476             # do we want this? maybe the other way around?
    477             raise TypeError, "unindexable object"
    478 
    479         #elif typ(self.g) in (t_FRAC, t_RFRAC):
     496            ## we return components based on the
     497            ## order elements are printed, so
     498            ##    Mod(3,7)[0]  is 3,
     499            ##    Mod(3,7)[1]  is 7.
     500            if n == 0:
     501                return P.new_ref(gel(self.g, 2), self)
     502            elif n == 1:
     503                return P.new_ref(gel(self.g, 1), self)
     504            else:
     505                raise IndexError, "index out of bounds"
     506           
     507
     508        #elif pari_type in (t_FRAC, t_RFRAC):
    480509            # generic code gives us:
    481510            #   [0] = numerator
    482511            #   [1] = denominator
    483512
    484         #elif typ(self.g) == t_COMPLEX:
     513        #elif pari_type == t_COMPLEX:
    485514            # generic code gives us
    486515            #   [0] = real part
    487516            #   [1] = imag part
    488517
    489         #elif type(self.g) in (t_QFR, t_QFI):
     518        #elif pari_type in (t_QFR, t_QFI):
    490519            # generic code works ok
    491520
    492521        else:
    cdef class gen(sage.structure.element.Ri 
    45764605        _sig_on
    45774606        return rnfisfree(self.g, t0)
    45784607
    4579 
     4608    def rnfisnorminit(self, polrel, flag=2):
     4609        _sig_on
     4610        return self.new_gen(rnfisnorminit(self.g, (<gen>polrel).g, flag))
     4611
     4612    def rnfisnorm(self, T, flag=0):
     4613        _sig_on
     4614        return self.new_gen(rnfisnorm((<gen>T).g, self.g, flag))
    45804615   
    45814616
    45824617
  • sage/rings/integer.pyx

    diff -r 59538ebc8f3b -r 585886192041 sage/rings/integer.pyx
    a b cdef class Integer(sage.structure.elemen 
    23332333            False
    23342334        """
    23352335        return mpz_perfect_power_p(self.value)
     2336
     2337    def is_norm(self, K, certify=True):
     2338        r"""
     2339        Determine whether or not self is a norm from K. If so, return
     2340        an element of K whose norm is self. If not, return False.
     2341
     2342        This uses Pari's rnfisnorm, whose results (in some cases) are
     2343        dependent on GRH. If certify=True, we have Pari that the
     2344        results are correct independent of GRH. In the case that K/QQ
     2345        is Galois, the Pari documentation suggests that the results
     2346        are valid even without certification.
     2347
     2348        EXAMPLES:
     2349            sage: K = NumberField(x**2-2,'beta')
     2350            sage: 4.is_norm(K)
     2351            -4*beta + 6
     2352            sage: 4.is_norm(K).norm()
     2353            4
     2354            sage: 5.is_norm(K)
     2355            False
     2356            sage: 7.is_norm(QQ)
     2357            7
     2358        """
     2359        from sage.rings.number_field.all import is_NumberField
     2360
     2361        if not is_NumberField(K):
     2362            raise ValueError, "K must be a NumberField"
     2363
     2364        if K.degree() == 1 or self.is_zero():
     2365            return self
     2366
     2367        if certify:
     2368            K.pari_bnf_certify()
     2369
     2370        rel_poly = K.pari_bnf()
     2371        base_poly = sage.libs.pari.gen.pari('y')
     2372        rnf_data = base_poly.rnfisnorminit(rel_poly)
     2373
     2374        x, q = self._pari_().rnfisnorm(rnf_data)
     2375
     2376        if not q.is_one():
     2377            return False
     2378        else:
     2379            deg = x[0].poldegree()+1
     2380            coeffs = [ x[0].polcoeff(i)._sage_() for i in range(deg) ]
     2381            return K(coeffs)
     2382
    23362383       
    23372384    def jacobi(self, b):
    23382385        r"""
  • sage/rings/number_field/number_field.py

    diff -r 59538ebc8f3b -r 585886192041 sage/rings/number_field/number_field.py
    a b class NumberField_generic(number_field_b 
    15141514
    15151515    def pari_bnf(self, certify=False, units=True):
    15161516        """
    1517         PARI big number field corresponding to this field.
     1517        Return the Pari bnf (Buchmann number field) corresponding to
     1518        this field.
     1519
     1520        If certify=True, once the bnf is created, certify that the
     1521        result is correct (i.e. does not depend on GRH).
     1522
     1523        The units flag controls how hard Pari tries to find a system
     1524        of fundamental units. If units=False, Pari will give up once
     1525        the default precision is insufficient. If units=True, it will
     1526        continue to try beyond this (though may eventually get stuck
     1527        if the coefficients of the units are quite large).
    15181528
    15191529        EXAMPLES:
    15201530            sage: k.<a> = NumberField(x^2 + 1); k
    class NumberField_generic(number_field_b 
    15671577                raise ValueError, "The result is not correct according to bnfcertify"
    15681578            self.__pari_bnf_certified = True
    15691579        return self.__pari_bnf_certified
     1580
     1581    def pari_rnfnorm_data(self, L):
     1582        """
     1583        Return the pari rnfisnorminit data corresponding to the
     1584        extension L/self.
     1585
     1586        EXAMPLES:
     1587            sage: K = NumberField(x**2-2,'alpha')
     1588            sage: L = K.extension(x**2+5, 'gamma')
     1589            sage: ls = K.pari_rnfnorm_data(L) ; len(ls)
     1590            8
     1591        """
     1592        if L.base_field() != self:
     1593            raise ValueError, "L must be an extension of self"
     1594
     1595        relpoly = L.defining_polynomial()
     1596        Kbnf = self.defining_polynomial()._pari_with_name('y').bnfinit()
     1597        polrel = sage.libs.pari.gen.pari([ a._pari_('y') for a in relpoly.coeffs() ]).Polrev()
     1598        return Kbnf.rnfisnorminit(polrel)
    15701599
    15711600    def characteristic(self):
    15721601        """
  • sage/rings/number_field/number_field_element.pyx

    diff -r 59538ebc8f3b -r 585886192041 sage/rings/number_field/number_field_element.pyx
    a b cdef class NumberFieldElement(FieldEleme 
    597597            1.2599
    598598        """
    599599        return self.number_field().complex_embeddings(prec)[i](self)
     600
     601    def is_norm(self, L, certify=True, rnf_data=None):
     602        r"""
     603        Determine whether or not self is a norm from L. If so, return
     604        an element of L whose norm is self. If not, return False.
     605
     606        This uses Pari's rnfisnorm, whose results (in some
     607        cases) are dependent on GRH. If certify=True, we have Pari
     608        that the results are correct independent of GRH. In the case
     609        that L/self.parent() is Galois, the Pari documentation suggests
     610        that the results are valid even without certification.
     611
     612        EXAMPLES:
     613            sage: K = NumberField(x**3+5, 'beta')
     614            sage: L = K.extension(x**2+x+1, 'gamma')
     615            sage: beta.is_norm(L)
     616            False
     617            sage: (beta**2).is_norm(L)
     618            beta*gamma + beta
     619            sage: (beta**2).is_norm(L).norm(K)
     620            beta^2
     621        """
     622        K = self.parent()
     623        if L == K or self.is_zero():
     624            return L(self)
     625
     626        if certify:
     627            K.pari_bnf_certify()
     628
     629        if rnf_data is None:
     630            rnf_data = self.parent().pari_rnfnorm_data(L)
     631
     632        x,q = self._pari_('y').rnfisnorm(rnf_data)
     633
     634        if not q.is_one():
     635            return False
     636        else:
     637            deg = x[0].poldegree()+1
     638            rep = [ x[0].polcoeff(i) for i in range(deg) ]
     639            coeffs = [ K(x.lift())  for x in rep ]
     640            gen = L.gen(0)
     641            elt = sum([ coeffs[i]*gen**i for i in range(deg) ])
     642            return elt
     643           
    600644
    601645    def is_totally_positive(self):
    602646        """
  • sage/rings/rational.pyx

    diff -r 59538ebc8f3b -r 585886192041 sage/rings/rational.pyx
    a b cdef class Rational(sage.structure.eleme 
    539539            False
    540540        """
    541541        return mpq_sgn(self.value) >= 0 and mpz_perfect_square_p(mpq_numref(self.value)) and mpz_perfect_square_p(mpq_denref(self.value))
     542
     543    def is_norm(self, K, certify=True):
     544        r"""
     545        Determine whether or not self is a norm from K. If so, return
     546        an element of K whose norm is self. If not, return False.
     547
     548        This uses Pari's rnfisnorm, whose results (in some cases) are
     549        dependent on GRH. If certify=True, we have Pari that the
     550        results are correct independent of GRH. In the case that K/QQ
     551        is Galois, the Pari documentation suggests that the results
     552        are valid even without certification.
     553
     554        EXAMPLES:
     555            sage: K = NumberField(x**2-2,'beta')
     556            sage: (1/7).is_norm(K)
     557            1/7*beta + 3/7
     558            sage: (1/10).is_norm(K)
     559            False
     560            sage: (1/691).is_norm(QQ)
     561            1/691
     562            sage: 0.is_norm(K)
     563            0
     564        """
     565        from sage.rings.number_field.all import is_NumberField
     566        QQ = self.parent()
     567
     568        if not is_NumberField(K):
     569            raise ValueError, "K must be a NumberField"
     570
     571        if K.degree() == 1 or self.is_zero():
     572            return self
     573
     574        if certify:
     575            K.pari_bnf_certify()
     576
     577        rel_poly = K.pari_bnf()
     578        base_poly = sage.libs.pari.gen.pari('y')
     579        rnf_data = base_poly.rnfisnorminit(rel_poly)
     580
     581        x, q = self._pari_().rnfisnorm(rnf_data)
     582
     583        if not q.is_one():
     584            return False
     585        else:
     586            deg = x[0].poldegree()+1
     587            coeffs = [ QQ(x[0].polcoeff(i)) for i in range(deg) ]
     588            return K(coeffs)
     589           
    542590
    543591    def squarefree_part(self):
    544592        """