Ticket #2329: trac_2329_rnfisnorm.patch

File trac_2329_rnfisnorm.patch, 17.4 KB (added by mstreng, 11 years ago)

apply only this latest file

  • sage/libs/pari/gen.pyx

    # HG changeset patch
    # User Marco Streng <marco.streng@gmail.com>
    # Date 1282140183 -7200
    # Node ID 47dfc1a7c27ee89022005314099aa6a74180da34
    # Parent  426be7b253ad9c3137e733aba26165a3de5b832f
    [mq]: rnfnormattempt
    
    diff -r 426be7b253ad -r 47dfc1a7c27e sage/libs/pari/gen.pyx
    a b  
    61506150        _sig_on
    61516151        return self.new_gen(bnfisintnorm(self.g, t0))
    61526152
     6153    def bnfisnorm(self, gen x, long flag=0):
     6154        t0GEN(x)
     6155        _sig_on
     6156        return self.new_gen(bnfisnorm(t0, self.g, flag, prec))
     6157
    61536158    def bnfisprincipal(self, x, long flag=1):
    61546159        t0GEN(x)
    61556160        _sig_on
     
    66786683        _sig_on
    66796684        return rnfisfree(self.g, t0)
    66806685
    6681 
    6682    
     6686    def rnfisnorminit(self, polrel, flag=2):
     6687        _sig_on
     6688        return self.new_gen(rnfisnorminit(self.g, (<gen>polrel).g, flag))
     6689
     6690    def rnfisnorm(self, T, flag=0):
     6691        _sig_on
     6692        return self.new_gen(rnfisnorm((<gen>T).g, self.g, flag))
    66836693
    66846694
    66856695    ##################################################
  • sage/rings/integer.pyx

    diff -r 426be7b253ad -r 47dfc1a7c27e sage/rings/integer.pyx
    a b  
    39943994            else:
    39953995                return False
    39963996        return mpz_perfect_power_p(self.value)
    3997        
     3997
     3998    def is_norm(self, K, element = False, proof = True):
     3999        r"""
     4000        See ``QQ(self).is_norm()``.
     4001       
     4002        EXAMPLES::
     4003
     4004            sage: K = NumberField(x**2 - 2, 'beta')
     4005            sage: n = 4
     4006            sage: n.is_norm(K)
     4007            True
     4008            sage: 5.is_norm(K)
     4009            False
     4010            sage: 7.is_norm(QQ)
     4011            True
     4012            sage: n.is_norm(K, element = True)
     4013            (True, -4*beta + 6)
     4014            sage: n.is_norm(K, element = True)[1].norm()
     4015            4
     4016            sage: n = 5
     4017            sage: n.is_norm(K, element = True)
     4018            (False, None)
     4019            sage: n = 7
     4020            sage: n.is_norm(QQ, element = True)
     4021            (True, 7)
     4022        """
     4023        from sage.rings.rational_field import QQ
     4024        return QQ(self).is_norm(K, element = element, proof = proof)
     4025
     4026    def bnfisnorm(self, K, certify = True, extra_primes = 0):
     4027        r"""
     4028        See ``QQ(self).bnfisnorm()``.
     4029       
     4030        EXAMPLES::
     4031       
     4032            sage: 3.bnfisnorm(QuadraticField(-1, 'i'))
     4033            (1, 3)
     4034            sage: 7.bnfisnorm(CyclotomicField(7))
     4035            (zeta7 - 1, 1)
     4036        """
     4037        from sage.rings.rational_field import QQ
     4038        return QQ(self).bnfisnorm(K, certify = certify, extra_primes = extra_primes)
     4039
     4040     
    39984041    def jacobi(self, b):
    39994042        r"""
    40004043        Calculate the Jacobi symbol `\left(\frac{self}{b}\right)`.
  • sage/rings/number_field/number_field.py

    diff -r 426be7b253ad -r 47dfc1a7c27e sage/rings/number_field/number_field.py
    a b  
    24882488            self.__pari_bnf_certified = True
    24892489        return self.__pari_bnf_certified
    24902490
     2491    def pari_rnfnorm_data(self, L):
     2492        """
     2493        Return the pari rnfisnorminit data corresponding to the
     2494        extension L/self.
     2495
     2496        EXAMPLES::
     2497       
     2498            sage: K = NumberField(x**2-2,'alpha')
     2499            sage: L = K.extension(x**2+5, 'gamma')
     2500            sage: ls = K.pari_rnfnorm_data(L) ; len(ls)
     2501            8
     2502        """
     2503        if L.base_field() != self:
     2504            raise ValueError, "L must be an extension of self"
     2505
     2506        relpoly = L.defining_polynomial()
     2507        Kbnf = self.defining_polynomial()._pari_with_name('y').bnfinit()
     2508        polrel = sage.libs.pari.gen.pari([ a._pari_('y') for a in relpoly.coeffs() ]).Polrev()
     2509        return Kbnf.rnfisnorminit(polrel)
     2510
    24912511    def _gap_init_(self):
    24922512        """
    24932513        Create a gap object representing self and return its name
  • sage/rings/number_field/number_field_element.pyx

    diff -r 426be7b253ad -r 47dfc1a7c27e sage/rings/number_field/number_field_element.pyx
    a b  
    918918        """
    919919        return self.number_field().complex_embeddings(prec)[i](self)
    920920
     921
     922    def is_norm(self, L, element = False, proof = True):
     923        r"""
     924        Determine whether self is the relative norm of an element
     925        of L/K, where K is self.parent().
     926       
     927        INPUT:
     928       
     929         - L -- a number field containing K=self.parent()
     930         - element -- True or False, whether to also output an element
     931           of which self is a norm
     932         - proof -- If True, then the output is correct unconditionally.
     933           If False, then the output assumes that the output of Pari's
     934           bnfinit is correct and assumes the Generalized Riemann Hypothesis.
     935       
     936        OUTPUT:
     937       
     938        If element is False, then the output is a boolean B, which is
     939        True if and only if self is the relative norm of an element of L
     940        to K.
     941        If element is False, then the output is a pair (B, x), where
     942        B is as above. If B is True, then x is an element of L such that
     943        self == x.norm(K). Otherwise, x is None.
     944       
     945        ALGORITHM:
     946       
     947        Uses Pari's rnfisnorm. See self.rnfisnorm().
     948
     949        EXAMPLES::
     950
     951            sage: K.<beta> = NumberField(x^3+5)
     952            sage: Q.<X> = K[]
     953            sage: L = K.extension(X^2+X+beta, 'gamma')
     954            sage: (beta/2).is_norm(L)
     955            False
     956            sage: beta.is_norm(L)
     957            True
     958
     959        Non-Galois number fields::
     960           
     961            sage: K.<a> = NumberField(x^2 + x + 1)
     962            sage: Q.<X> = K[]
     963            sage: L.<b> = NumberField(X^3 + a)
     964            sage: (a/3).is_norm(L)
     965            True
     966            sage: (a/2).is_norm(L)
     967            Traceback (most recent call last):
     968            ...
     969            NotImplementedError: is_norm is not implemented unconditionally for norms from non-Galois number fields
     970            sage: (a/2).is_norm(L, proof = False)
     971            False
     972
     973            sage: K.<a> = NumberField(x^3 + x + 1)
     974            sage: Q.<X> = K[]
     975            sage: L.<b> = NumberField(X^4 + a)
     976            sage: t = (-a).is_norm(L, element = True); t
     977            (True, b^3 + 1)
     978            sage: t[1].norm(K)
     979            -a
     980        """
     981        if not element:
     982            return self.is_norm(L, element = True, proof = proof)[0]
     983
     984        K = self.parent()
     985        from sage.rings.number_field.all import is_AbsoluteNumberField, \
     986                                                is_NumberField, \
     987                                                is_RelativeNumberField
     988        if not is_NumberField(L):
     989            raise ValueError, "L (=%s) must be a NumberField in is_norm" % L
     990       
     991        if is_AbsoluteNumberField(L):
     992            Lrel = L.relativize(K.hom(L), ('a', 'b'))
     993            b, x = self.is_norm(Lrel, element = True, proof = proof)
     994            h = Lrel.structure()[0]
     995            return b, h(x)
     996
     997        if L.relative_degree() == 1 or self.is_zero():
     998            return True, L(self)
     999
     1000        a, b = self.rnfisnorm(L, certify = proof)
     1001        if b == 1:
     1002            assert a.norm(K) == self
     1003            return True, a
     1004
     1005        if L.is_galois_relative():
     1006            return False, None
     1007
     1008        # The following gives the galois closure of K/QQ, but the galois
     1009        # closure of K/self.parent() would suffice.
     1010        M = L.galois_closure('a')
     1011        from sage.functions.log import log
     1012        from sage.functions.other import floor
     1013        extra_primes = floor(12*log(abs(M.discriminant()))**2)
     1014        a, b = self.rnfisnorm(L, certify = proof, extra_primes = extra_primes)
     1015        if b == 1:
     1016            assert a.norm(K) == self
     1017            return True, a
     1018
     1019        if proof:
     1020            raise NotImplementedError, "is_norm is not implemented unconditionally for norms from non-Galois number fields"
     1021        return False, None
     1022
     1023    def rnfisnorm(self, L, certify = True, extra_primes = 0):
     1024        r"""
     1025        Gives the output of the Pari function rnfisnorm.
     1026       
     1027        This tries to decide whether the number field element self is
     1028        the norm of some x in the extension L/K (with K = self.parent()).
     1029
     1030        The output is a pair (x, q), where self = Norm(x)*q. The
     1031        algorithm looks for a solution x that is an S-integer, with S
     1032        a list of places of L containing at least the ramified primes,
     1033        the generators of the class group of L, as well as those primes
     1034        dividing self.
     1035       
     1036        If L/K is Galois, then this is enough; otherwise,
     1037        extra_primes is used to add more primes to S: all the places
     1038        above the primes p <= extra_primes (resp. p|extra_primes) if
     1039        extra_primes > 0 (resp. extra_primes < 0).
     1040
     1041        The answer is guaranteed (i.e. self is a norm iff q = 1) if the
     1042        field is Galois, or, under GRH, if S contains all primes less
     1043        than 12log^2|\disc(M)|, where M is the normal closure of L/K.
     1044
     1045        INPUT:
     1046       
     1047         - L -- a relative number field with base field self.parent()
     1048         - certify -- whether to certify the outputs of Pari init functions
     1049           used in the computation
     1050         - extra_primes -- an integer as explained above.
     1051
     1052        OUTPUT:
     1053       
     1054        A pair (x, q) with x in L and q in K as explained above
     1055        such that self == x.norm(K)*q.
     1056       
     1057        ALGORITHM:
     1058       
     1059        Uses Pari's rnfisnorm.
     1060       
     1061        EXAMPLES::
     1062       
     1063            sage: K.<a> = NumberField(x^3 + x^2 - 2*x - 1, 'a')
     1064            sage: P.<X> = K[]
     1065            sage: L = NumberField(X^2 + a^2 + 2*a + 1, 'b')
     1066            sage: K(17).rnfisnorm(L)
     1067            ((a^2 - 2)*b - 4, 1)
     1068           
     1069            sage: P.<x> = QQ[]
     1070            sage: K.<a> = NumberField(x^3 + x + 1)
     1071            sage: Q.<X> = K[]
     1072            sage: L.<b> = NumberField(X^4 + a)
     1073            sage: t = (-a).rnfisnorm(L); t
     1074            (b^3 + 1, 1)
     1075            sage: t[0].norm(K)
     1076            -a
     1077            sage: t = K(3).rnfisnorm(L); t
     1078            ((-a^2 - 1)*b^3 + b^2 + a*b + a^2 + 1, -3*a)
     1079            sage: t[0].norm(K)*t[1]
     1080            3
     1081        """
     1082        K = self.parent()
     1083        from sage.rings.number_field.all import is_RelativeNumberField
     1084        if (not is_RelativeNumberField(L)) or L.base_field() != K:
     1085            raise ValueError, "L (=%s) must be a relative number field with base field K (=%s) in rnfisnorm" % (L, K)
     1086
     1087        if certify:
     1088            K.pari_bnf_certify()
     1089
     1090        rnf_data = self.parent().pari_rnfnorm_data(L)
     1091        x, q = self._pari_('y').rnfisnorm(rnf_data)
     1092
     1093        degL = L.relative_degree()
     1094        repx = [ x.lift().polcoeff(i) for i in range(degL) ]
     1095        coeffsx = [ K(x.lift())  for x in repx ]
     1096        genL = L.gen(0)
     1097        x = sum([ coeffsx[i]*genL**i for i in range(degL) ])
     1098
     1099        degK = K.degree()
     1100        coeffsq = [ q.lift().polcoeff(i)._sage_() for i in range(degK) ]
     1101        q = K(coeffsq)
     1102
     1103        return x, q
     1104           
     1105
    9211106    def _mpfr_(self, R):
    9221107        """
    9231108        EXAMPLES::
  • sage/rings/rational.pyx

    diff -r 426be7b253ad -r 47dfc1a7c27e sage/rings/rational.pyx
    a b  
    11651165        """
    11661166        return mpq_sgn(self.value) >= 0 and mpz_perfect_square_p(mpq_numref(self.value)) and mpz_perfect_square_p(mpq_denref(self.value))
    11671167
     1168    def is_norm(self, L, element = False, proof = True):
     1169        r"""
     1170        Determine whether self is the norm of an element of L.
     1171       
     1172        INPUT:
     1173       
     1174         - L -- a number field
     1175         - element -- True or False, whether to also output an element
     1176           of which self is a norm
     1177         - proof -- If True, then the output is correct unconditionally.
     1178           If False, then the output assumes that the output of Pari's
     1179           bnfinit is correct and assumes the Generalized Riemann Hypothesis.
     1180       
     1181        OUTPUT:
     1182       
     1183        If element is False, then the output is a boolean B, which is
     1184        True if and only if self is the norm of an element of L.
     1185        If element is False, then the output is a pair (B, x), where
     1186        B is as above. If B is True, then x an element of L such that
     1187        self == x.norm(). Otherwise, x is None.
     1188       
     1189        ALGORITHM:
     1190       
     1191        Uses Pari's bnfisnorm. See self.bnfisnorm().
     1192
     1193        EXAMPLES::
     1194
     1195            sage: K = NumberField(x**2 - 2, 'beta')
     1196            sage: (1/7).is_norm(K)
     1197            True
     1198            sage: (1/10).is_norm(K)
     1199            False
     1200            sage: 0.is_norm(K)
     1201            True
     1202            sage: (1/7).is_norm(K, element = True)
     1203            (True, 1/7*beta + 3/7)
     1204            sage: (1/10).is_norm(K, element = True)
     1205            (False, None)
     1206            sage: (1/691).is_norm(QQ, element = True)
     1207            (True, 1/691)
     1208
     1209        The number field doesn't have to be defined by an
     1210        integral polynomial::
     1211           
     1212            sage: (1/5).is_norm(QuadraticField(5/4, 'a'), element = True)
     1213            (True, -1/5*a - 1/2)
     1214           
     1215        A non-Galois number field::
     1216       
     1217            sage: K.<b> = NumberField(x^3-2)
     1218            sage: x, y = (3/5).is_norm(K, element = True); x
     1219            True
     1220            sage: y.norm()
     1221            3/5
     1222           
     1223            sage: 7.is_norm(K)
     1224            Traceback (most recent call last):
     1225            ...
     1226            NotImplementedError: is_norm is not implemented unconditionally for norms from non-Galois number fields
     1227            sage: 7.is_norm(K, proof = False)
     1228            False
     1229        """
     1230        if not element:
     1231            return self.is_norm(L, element = True, proof = proof)[0]
     1232        from sage.rings.number_field.all import is_NumberField
     1233        if not is_NumberField(L):
     1234            raise ValueError, "L (=%s) must be a NumberField in is_norm" % L
     1235        if L.degree() == 1 or self.is_zero():
     1236            return True, L(self)
     1237        d = L.polynomial().denominator()
     1238        if not d == 1:
     1239            M, M_to_L = L.subfield(L.gen()*d)
     1240            b, x = self.is_norm(M, element = True, proof = proof)
     1241            if b:
     1242                x = M_to_L(x)
     1243            return b, x
     1244        a, b = self.bnfisnorm(L, certify = proof)
     1245        if b == 1:
     1246            assert a.norm() == self
     1247            return True, a
     1248        if L.is_galois():
     1249            return False, None
     1250        M = L.galois_closure('a')
     1251        from sage.functions.log import log
     1252        from sage.functions.other import floor
     1253        extra_primes = floor(12*log(abs(M.discriminant()))**2)
     1254        a, b = self.bnfisnorm(L, certify = proof, extra_primes = extra_primes)
     1255        if b == 1:
     1256            assert a.norm() == self
     1257            return True, a
     1258        if proof:
     1259            raise NotImplementedError, "is_norm is not implemented unconditionally for norms from non-Galois number fields"
     1260        return False, None
     1261
     1262    def bnfisnorm(self, K, certify = True, extra_primes = 0):
     1263        r"""
     1264        This gives the output of the Pari function bnfisnorm.
     1265       
     1266        Tries to tell whether the rational number self is the norm of some
     1267        element y in K. Returns a pair (a, b) where self = Norm(a)*b. Looks for
     1268        a solution that is an S-unit, with S a certain set of prime ideals
     1269        containing (among others) all primes dividing self.
     1270       
     1271        If K is known to be Galois, set extra_primes = 0 (in this case, self
     1272        is a norm iff b = 1).
     1273       
     1274        If extra_primes is non-zero, the program adds to S the following
     1275        prime ideals, depending on the sign of extra_primes.
     1276        If extra_primes > 0, the ideals of norm less than extra_primes.
     1277        And if extra_primes < 0, the ideals dividing extra_primes.
     1278
     1279        Assuming GRH, the answer is guaranteed (i.e., self is a norm
     1280        iff b = 1), if S contains all primes less than 12log(\disc(L))^2,
     1281        where L is the Galois closure of K.
     1282
     1283        INPUT:
     1284       
     1285         - K -- a number field
     1286         - certify -- whether to certify the output of bnfinit that is used
     1287           in the computation
     1288         - extra_primes -- an integer as explained above
     1289
     1290        OUTPUT:
     1291       
     1292        A pair (a, b) with a in K and b in `QQ` such that self == Norm(a)*b
     1293        as explained above.
     1294       
     1295        ALGORITHM:
     1296       
     1297        Uses Pari's bnfisnorm.
     1298       
     1299        EXAMPLES::
     1300       
     1301            sage: (1/2).bnfisnorm(QuadraticField(-1, 'i'))
     1302            (-1/2*i + 1/2, 1)
     1303            sage: (1/3).bnfisnorm(CyclotomicField(7))
     1304            (1/3, 243)
     1305            sage: 7.bnfisnorm(NumberField(x^3-2, 'b'))
     1306            (1, 7)
     1307        """
     1308        from sage.rings.number_field.all import is_NumberField
     1309        if not is_NumberField(K):
     1310            raise ValueError, "K must be a NumberField in bnfisnorm"
     1311        if certify:
     1312            K.pari_bnf_certify()
     1313
     1314        a, b = self._pari_().bnfisnorm(K.pari_bnf(), flag = extra_primes)
     1315        deg = K.degree()
     1316        coeffs = [ a.lift().polcoeff(i)._sage_() for i in range(deg) ]
     1317        from sage.rings.rational_field import QQ
     1318        return K(coeffs), QQ(b._sage_())
     1319
     1320
    11681321    def is_perfect_power(self, expected_value=False):
    11691322        r"""
    11701323        Returns ``True`` if self is a perfect power.