Ticket #2329: trac_2329_rnfisnorm2.patch

File trac_2329_rnfisnorm2.patch, 19.7 KB (added by mstreng, 11 years ago)

apply only this latest file (works on sage 4.6.1.alpha2)

  • sage/libs/pari/decl.pxi

    # HG changeset patch
    # User Marco Streng <marco.streng@gmail.com>
    # Date 1282140183 -7200
    # Node ID 0c15340b37188dde8d2d7e316a35cbffae8e4fcd
    # Parent  e369cc8bfa30fbab80056966a4d484c1eb2766f6
    Trac: 2329: add interface to rnfisnorm
    
    diff -r e369cc8bfa30 -r 0c15340b3718 sage/libs/pari/decl.pxi
    a b  
    695695
    696696    # buch4.c
    697697
    698     GEN     bnfisnorm(GEN bnf,GEN x,long flag,long PREC)
     698    GEN     bnfisnorm(GEN bnf, GEN x, long flag)
    699699    GEN     rnfisnorm(GEN S, GEN x, long flag)
     700    GEN     rnfisnorminit(GEN T, GEN relpol, int galois)
    700701    GEN     bnfissunit(GEN bnf,GEN suni,GEN x)
    701702    GEN     bnfsunit(GEN bnf,GEN s,long PREC)
    702703    long    nfhilbert(GEN bnf,GEN a,GEN b)
  • sage/libs/pari/gen.pyx

    diff -r e369cc8bfa30 -r 0c15340b3718 sage/libs/pari/gen.pyx
    a b  
    65546554        sig_on()
    65556555        return self.new_gen(bnfisintnorm(self.g, t0))
    65566556
     6557    def bnfisnorm(self, gen x, long flag=0):
     6558        t0GEN(x)
     6559        sig_on()
     6560        return self.new_gen(bnfisnorm(t0, self.g, flag))
     6561
    65576562    def bnfisprincipal(self, x, long flag=1):
    65586563        t0GEN(x)
    65596564        sig_on()
     
    76267631        return self.new_gen(thueinit(self.g, flag, prec))
    76277632
    76287633
    7629 
    7630    
     7634    def rnfisnorminit(self, polrel, flag=2):
     7635        sig_on()
     7636        return self.new_gen(rnfisnorminit(self.g, (<gen>polrel).g, flag))
     7637
     7638    def rnfisnorm(self, T, flag=0):
     7639        sig_on()
     7640        return self.new_gen(rnfisnorm((<gen>T).g, self.g, flag))
    76317641
    76327642    ###########################################
    76337643    # 8: Vectors, matrices, LINEAR ALGEBRA and sets
  • sage/rings/integer.pyx

    diff -r e369cc8bfa30 -r 0c15340b3718 sage/rings/integer.pyx
    a b  
    41524152            else:
    41534153                return False
    41544154        return mpz_perfect_power_p(self.value)
    4155        
     4155
     4156    def is_norm(self, K, element = False, proof = True):
     4157        r"""
     4158        See ``QQ(self).is_norm()``.
     4159       
     4160        EXAMPLES::
     4161
     4162            sage: K = NumberField(x**2 - 2, 'beta')
     4163            sage: n = 4
     4164            sage: n.is_norm(K)
     4165            True
     4166            sage: 5.is_norm(K)
     4167            False
     4168            sage: 7.is_norm(QQ)
     4169            True
     4170            sage: n.is_norm(K, element = True)
     4171            (True, 4*beta + 6)
     4172            sage: n.is_norm(K, element = True)[1].norm()
     4173            4
     4174            sage: n = 5
     4175            sage: n.is_norm(K, element = True)
     4176            (False, None)
     4177            sage: n = 7
     4178            sage: n.is_norm(QQ, element = True)
     4179            (True, 7)
     4180
     4181        """
     4182        from sage.rings.rational_field import QQ
     4183        return QQ(self).is_norm(K, element = element, proof = proof)
     4184
     4185    def bnfisnorm(self, K, certify = True, extra_primes = 0):
     4186        r"""
     4187        See ``QQ(self).bnfisnorm()``.
     4188       
     4189        EXAMPLES::
     4190       
     4191            sage: 3.bnfisnorm(QuadraticField(-1, 'i'))
     4192            (1, 3)
     4193            sage: 7.bnfisnorm(CyclotomicField(7))
     4194            (-zeta7^2 + zeta7, 1)
     4195        """
     4196        from sage.rings.rational_field import QQ
     4197        return QQ(self).bnfisnorm(K, certify = certify, extra_primes = extra_primes)
     4198
     4199     
    41564200    def jacobi(self, b):
    41574201        r"""
    41584202        Calculate the Jacobi symbol `\left(\frac{self}{b}\right)`.
  • sage/rings/number_field/number_field.py

    diff -r e369cc8bfa30 -r 0c15340b3718 sage/rings/number_field/number_field.py
    a b  
    25922592            self.__pari_bnf_certified = True
    25932593        return self.__pari_bnf_certified
    25942594
     2595    def pari_rnfnorm_data(self, L):
     2596        """
     2597        Return the pari rnfisnorminit data corresponding to the
     2598        extension L/self.
     2599
     2600        EXAMPLES::
     2601       
     2602            sage: K = NumberField(x**2-2,'alpha')
     2603            sage: L = K.extension(x**2+5, 'gamma')
     2604            sage: ls = K.pari_rnfnorm_data(L) ; len(ls)
     2605            8
     2606
     2607            sage: K.<a> = NumberField(x^2 + x + 1)
     2608            sage: P.<X> = K[]
     2609            sage: L.<b> = NumberField(X^3 + a)
     2610            sage: ls = K.pari_rnfnorm_data(L); len(ls)
     2611            8
     2612        """
     2613        if L.base_field() != self:
     2614            raise ValueError, "L must be an extension of self"
     2615       
     2616        relpoly = L.defining_polynomial()
     2617        Kbnf = self.defining_polynomial()._pari_with_name('y').bnfinit()
     2618        coeffs = [ a._pari_('y') for a in relpoly.coeffs() ]
     2619
     2620        # The following is a fix for pari bug #1144, and can
     2621        # be removed once the bug fix reaches sage.
     2622        if not relpoly.is_monic():
     2623            raise ValueError, "Number field L (=%s) must be defined by a monic polynomial in pari_rnfisnorm_data" % L
     2624        coeffs[-1] = ZZ(1)._pari_()
     2625       
     2626        polrel = sage.libs.pari.gen.pari(coeffs).Polrev()
     2627        return Kbnf.rnfisnorminit(polrel)
     2628
    25952629    def _gap_init_(self):
    25962630        """
    25972631        Create a gap object representing self and return its name
  • sage/rings/number_field/number_field_element.pyx

    diff -r e369cc8bfa30 -r 0c15340b3718 sage/rings/number_field/number_field_element.pyx
    a b  
    936936        """
    937937        return self.number_field().complex_embeddings(prec)[i](self)
    938938
     939
     940    def is_norm(self, L, element = False, proof = True):
     941        r"""
     942        Determine whether self is the relative norm of an element
     943        of L/K, where K is self.parent().
     944       
     945        INPUT:
     946       
     947         - L -- a number field containing K=self.parent()
     948         - element -- True or False, whether to also output an element
     949           of which self is a norm
     950         - proof -- If True, then the output is correct unconditionally.
     951           If False, then the output is correct under GRH.
     952       
     953        OUTPUT:
     954       
     955        If element is False, then the output is a boolean B, which is
     956        True if and only if self is the relative norm of an element of L
     957        to K.
     958        If element is False, then the output is a pair (B, x), where
     959        B is as above. If B is True, then x is an element of L such that
     960        self == x.norm(K). Otherwise, x is None.
     961       
     962        ALGORITHM:
     963       
     964        Uses Pari's rnfisnorm. See self.rnfisnorm().
     965
     966        EXAMPLES::
     967
     968            sage: K.<beta> = NumberField(x^3+5)
     969            sage: Q.<X> = K[]
     970            sage: L = K.extension(X^2+X+beta, 'gamma')
     971            sage: (beta/2).is_norm(L)
     972            False
     973            sage: beta.is_norm(L)
     974            True
     975
     976        Non-Galois number fields::
     977           
     978            sage: K.<a> = NumberField(x^2 + x + 1)
     979            sage: Q.<X> = K[]
     980            sage: L.<b> = NumberField(X^3 + a)
     981            sage: (a/3).is_norm(L)
     982            True
     983            sage: (a/2).is_norm(L)
     984            Traceback (most recent call last):
     985            ...
     986            NotImplementedError: is_norm is not implemented unconditionally for norms from non-Galois number fields
     987            sage: (a/2).is_norm(L, proof = False)
     988            False
     989
     990            sage: K.<a> = NumberField(x^3 + x + 1)
     991            sage: Q.<X> = K[]
     992            sage: L.<b> = NumberField(X^4 + a)
     993            sage: t = (-a).is_norm(L, element = True); t
     994            (True, b^3 + 1)
     995            sage: t[1].norm(K)
     996            -a
     997
     998        AUTHORS:
     999
     1000        - Craig Citro (2008-04-05)
     1001
     1002        - Marco Streng (2010-12-03)
     1003        """
     1004        if not element:
     1005            return self.is_norm(L, element = True, proof = proof)[0]
     1006
     1007        K = self.parent()
     1008        from sage.rings.number_field.all import is_AbsoluteNumberField, \
     1009                                                is_NumberField, \
     1010                                                is_RelativeNumberField
     1011        if not is_NumberField(L):
     1012            raise ValueError, "L (=%s) must be a NumberField in is_norm" % L
     1013       
     1014        if is_AbsoluteNumberField(L):
     1015            Lrel = L.relativize(K.hom(L), ('a', 'b'))
     1016            b, x = self.is_norm(Lrel, element = True, proof = proof)
     1017            h = Lrel.structure()[0]
     1018            return b, h(x)
     1019
     1020        if L.relative_degree() == 1 or self.is_zero():
     1021            return True, L(self)
     1022
     1023        a, b = self.rnfisnorm(L, certify = proof)
     1024        if b == 1:
     1025            assert a.norm(K) == self
     1026            return True, a
     1027
     1028        if L.is_galois_relative():
     1029            return False, None
     1030
     1031        # The following gives the galois closure of K/QQ, but the galois
     1032        # closure of K/self.parent() would suffice.
     1033        M = L.galois_closure('a')
     1034        from sage.functions.log import log
     1035        from sage.functions.other import floor
     1036        extra_primes = floor(12*log(abs(M.discriminant()))**2)
     1037        a, b = self.rnfisnorm(L, certify = proof, extra_primes = extra_primes)
     1038        if b == 1:
     1039            assert a.norm(K) == self
     1040            return True, a
     1041
     1042        if proof:
     1043            raise NotImplementedError, "is_norm is not implemented unconditionally for norms from non-Galois number fields"
     1044        return False, None
     1045
     1046    def rnfisnorm(self, L, certify = True, extra_primes = 0):
     1047        r"""
     1048        Gives the output of the Pari function rnfisnorm.
     1049       
     1050        This tries to decide whether the number field element self is
     1051        the norm of some x in the extension L/K (with K = self.parent()).
     1052
     1053        The output is a pair (x, q), where self = Norm(x)*q. The
     1054        algorithm looks for a solution x that is an S-integer, with S
     1055        a list of places of L containing at least the ramified primes,
     1056        the generators of the class group of L, as well as those primes
     1057        dividing self.
     1058       
     1059        If L/K is Galois, then this is enough; otherwise,
     1060        extra_primes is used to add more primes to S: all the places
     1061        above the primes p <= extra_primes (resp. p|extra_primes) if
     1062        extra_primes > 0 (resp. extra_primes < 0).
     1063
     1064        The answer is guaranteed (i.e. self is a norm iff q = 1) if the
     1065        field is Galois, or, under GRH, if S contains all primes less
     1066        than 12log^2|\disc(M)|, where M is the normal closure of L/K.
     1067
     1068        INPUT:
     1069       
     1070         - L -- a relative number field with base field self.parent()
     1071         - certify -- whether to certify outputs of Pari init functions.
     1072           If false, truth of the output depends on GRH.
     1073         - extra_primes -- an integer as explained above.
     1074
     1075        OUTPUT:
     1076       
     1077        A pair (x, q) with x in L and q in K as explained above
     1078        such that self == x.norm(K)*q.
     1079       
     1080        ALGORITHM:
     1081       
     1082        Uses Pari's rnfisnorm.
     1083       
     1084        EXAMPLES::
     1085       
     1086            sage: K.<a> = NumberField(x^3 + x^2 - 2*x - 1, 'a')
     1087            sage: P.<X> = K[]
     1088            sage: L = NumberField(X^2 + a^2 + 2*a + 1, 'b')
     1089            sage: K(17).rnfisnorm(L)
     1090            ((a^2 - 2)*b - 4, 1)
     1091           
     1092            sage: P.<x> = QQ[]
     1093            sage: K.<a> = NumberField(x^3 + x + 1)
     1094            sage: Q.<X> = K[]
     1095            sage: L.<b> = NumberField(X^4 + a)
     1096            sage: t = (-a).rnfisnorm(L); t
     1097            (b^3 + 1, 1)
     1098            sage: t[0].norm(K)
     1099            -a
     1100            sage: t = K(3).rnfisnorm(L); t
     1101            ((-a^2 - 1)*b^3 + b^2 + a*b + a^2 + 1, -3*a)
     1102            sage: t[0].norm(K)*t[1]
     1103            3
     1104
     1105        AUTHORS:
     1106
     1107        - Craig Citro (2008-04-05)
     1108
     1109        - Marco Streng (2010-12-03)
     1110        """
     1111        K = self.parent()
     1112        from sage.rings.number_field.all import is_RelativeNumberField
     1113        if (not is_RelativeNumberField(L)) or L.base_field() != K:
     1114            raise ValueError, "L (=%s) must be a relative number field with base field K (=%s) in rnfisnorm" % (L, K)
     1115
     1116        if certify:
     1117            K.pari_bnf_certify()
     1118
     1119        # The following paragraph is a workaround for pari bug #1143,
     1120        # which has been fixed in pari revision 12769. The workaround
     1121        # can be removed once that revision reaches sage.
     1122        if self.denominator() != 1:
     1123            den = self.denominator()
     1124            integral_self = self*den**L.relative_degree()
     1125            (x, q) = integral_self.rnfisnorm(L = L, certify = certify, \
     1126                                     extra_primes = extra_primes)
     1127            return (x/den, q)   
     1128
     1129
     1130        rnf_data = self.parent().pari_rnfnorm_data(L)
     1131        x, q = self._pari_('y').rnfisnorm(rnf_data)
     1132
     1133        degL = L.relative_degree()
     1134        repx = [ x.lift().polcoeff(i) for i in range(degL) ]
     1135        coeffsx = [ K(x.lift())  for x in repx ]
     1136        genL = L.gen(0)
     1137        x = sum([ coeffsx[i]*genL**i for i in range(degL) ])
     1138
     1139        degK = K.degree()
     1140        coeffsq = [ q.lift().polcoeff(i)._sage_() for i in range(degK) ]
     1141        q = K(coeffsq)
     1142
     1143        return x, q
     1144           
     1145
    9391146    def _mpfr_(self, R):
    9401147        """
    9411148        EXAMPLES::
  • sage/rings/rational.pyx

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