Ticket #2329: trac_2329_rnfisnorm3.patch

File trac_2329_rnfisnorm3.patch, 19.8 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 991e022e2c68548175fc5a227bde1be0568a8625
    # Parent  e369cc8bfa30fbab80056966a4d484c1eb2766f6
    Trac: 2329: add interface to rnfisnorm
    
    diff -r e369cc8bfa30 -r 991e022e2c68 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 991e022e2c68 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        t0GEN(polrel)
     7636        sig_on()
     7637        return self.new_gen(rnfisnorminit(self.g, t0, flag))
     7638
     7639    def rnfisnorm(self, T, flag=0):
     7640        t0GEN(T)
     7641        sig_on()
     7642        return self.new_gen(rnfisnorm(t0, self.g, flag))
    76317643
    76327644    ###########################################
    76337645    # 8: Vectors, matrices, LINEAR ALGEBRA and sets
  • sage/rings/integer.pyx

    diff -r e369cc8bfa30 -r 991e022e2c68 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 991e022e2c68 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 991e022e2c68 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        # The following paragraph is a workaround for pari bug #1143,
     1008        # which has been fixed in pari revision 12769. The workaround
     1009        # can be removed once that revision reaches sage.
     1010        # See also sage trac ticket #10430
     1011        if self.denominator() != 1:
     1012            den = self.denominator()
     1013            integral_self = self*den**L.relative_degree()
     1014            x, q = integral_self.is_norm(L = L, element = True,
     1015                                         proof = proof)
     1016            if x:
     1017                return True, q/den
     1018            return False, None
     1019
     1020        K = self.parent()
     1021        from sage.rings.number_field.all import is_AbsoluteNumberField, \
     1022                                                is_NumberField, \
     1023                                                is_RelativeNumberField
     1024        if not is_NumberField(L):
     1025            raise ValueError, "L (=%s) must be a NumberField in is_norm" % L
     1026       
     1027        if is_AbsoluteNumberField(L):
     1028            Lrel = L.relativize(K.hom(L), ('a', 'b'))
     1029            b, x = self.is_norm(Lrel, element = True, proof = proof)
     1030            h = Lrel.structure()[0]
     1031            return b, h(x)
     1032
     1033        if L.relative_degree() == 1 or self.is_zero():
     1034            return True, L(self)
     1035
     1036        a, b = self.rnfisnorm(L, certify = proof)
     1037        if b == 1:
     1038            assert a.norm(K) == self
     1039            return True, a
     1040
     1041        if L.is_galois_relative():
     1042            return False, None
     1043
     1044        # The following gives the galois closure of K/QQ, but the galois
     1045        # closure of K/self.parent() would suffice.
     1046        M = L.galois_closure('a')
     1047        from sage.functions.log import log
     1048        from sage.functions.other import floor
     1049        extra_primes = floor(12*log(abs(M.discriminant()))**2)
     1050        a, b = self.rnfisnorm(L, certify = proof, extra_primes = extra_primes)
     1051        if b == 1:
     1052            assert a.norm(K) == self
     1053            return True, a
     1054
     1055        if proof:
     1056            raise NotImplementedError, "is_norm is not implemented unconditionally for norms from non-Galois number fields"
     1057        return False, None
     1058
     1059    def rnfisnorm(self, L, certify = True, extra_primes = 0):
     1060        r"""
     1061        Gives the output of the Pari function rnfisnorm.
     1062       
     1063        This tries to decide whether the number field element self is
     1064        the norm of some x in the extension L/K (with K = self.parent()).
     1065
     1066        The output is a pair (x, q), where self = Norm(x)*q. The
     1067        algorithm looks for a solution x that is an S-integer, with S
     1068        a list of places of L containing at least the ramified primes,
     1069        the generators of the class group of L, as well as those primes
     1070        dividing self.
     1071       
     1072        If L/K is Galois, then this is enough; otherwise,
     1073        extra_primes is used to add more primes to S: all the places
     1074        above the primes p <= extra_primes (resp. p|extra_primes) if
     1075        extra_primes > 0 (resp. extra_primes < 0).
     1076
     1077        The answer is guaranteed (i.e. self is a norm iff q = 1) if the
     1078        field is Galois, or, under GRH, if S contains all primes less
     1079        than 12log^2|\disc(M)|, where M is the normal closure of L/K.
     1080
     1081        INPUT:
     1082       
     1083         - L -- a relative number field with base field self.parent()
     1084         - certify -- whether to certify outputs of Pari init functions.
     1085           If false, truth of the output depends on GRH.
     1086         - extra_primes -- an integer as explained above.
     1087
     1088        OUTPUT:
     1089       
     1090        A pair (x, q) with x in L and q in K as explained above
     1091        such that self == x.norm(K)*q.
     1092       
     1093        ALGORITHM:
     1094       
     1095        Uses Pari's rnfisnorm.
     1096       
     1097        EXAMPLES::
     1098       
     1099            sage: K.<a> = NumberField(x^3 + x^2 - 2*x - 1, 'a')
     1100            sage: P.<X> = K[]
     1101            sage: L = NumberField(X^2 + a^2 + 2*a + 1, 'b')
     1102            sage: K(17).rnfisnorm(L)
     1103            ((a^2 - 2)*b - 4, 1)
     1104           
     1105            sage: P.<x> = QQ[]
     1106            sage: K.<a> = NumberField(x^3 + x + 1)
     1107            sage: Q.<X> = K[]
     1108            sage: L.<b> = NumberField(X^4 + a)
     1109            sage: t = (-a).rnfisnorm(L); t
     1110            (b^3 + 1, 1)
     1111            sage: t[0].norm(K)
     1112            -a
     1113            sage: t = K(3).rnfisnorm(L); t
     1114            ((-a^2 - 1)*b^3 + b^2 + a*b + a^2 + 1, -3*a)
     1115            sage: t[0].norm(K)*t[1]
     1116            3
     1117
     1118        AUTHORS:
     1119
     1120        - Craig Citro (2008-04-05)
     1121
     1122        - Marco Streng (2010-12-03)
     1123        """
     1124        K = self.parent()
     1125        from sage.rings.number_field.all import is_RelativeNumberField
     1126        if (not is_RelativeNumberField(L)) or L.base_field() != K:
     1127            raise ValueError, "L (=%s) must be a relative number field with base field K (=%s) in rnfisnorm" % (L, K)
     1128
     1129        if certify:
     1130            K.pari_bnf_certify()
     1131
     1132        rnf_data = self.parent().pari_rnfnorm_data(L)
     1133        x, q = self._pari_('y').rnfisnorm(rnf_data)
     1134
     1135        degL = L.relative_degree()
     1136        repx = [ x.lift().polcoeff(i) for i in range(degL) ]
     1137        coeffsx = [ K(x.lift())  for x in repx ]
     1138        genL = L.gen(0)
     1139        x = sum([ coeffsx[i]*genL**i for i in range(degL) ])
     1140
     1141        degK = K.degree()
     1142        coeffsq = [ q.lift().polcoeff(i)._sage_() for i in range(degK) ]
     1143        q = K(coeffsq)
     1144
     1145        return x, q
     1146           
     1147
    9391148    def _mpfr_(self, R):
    9401149        """
    9411150        EXAMPLES::
  • sage/rings/rational.pyx

    diff -r e369cc8bfa30 -r 991e022e2c68 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
     1241        # The following is a workaround for pari bug #1143, which is
     1242        # fixed in pari revision 12769. The workaround can be removed
     1243        # once that revision reaches sage. See also sage trac #10430
     1244        if self.denominator() != 1:
     1245            den = self.denominator()
     1246            a, b = (self*den**L.degree()).is_norm(L, element = True, \
     1247                                                  proof = proof)
     1248            if a:
     1249                return True, b/den
     1250            return False, None
     1251
     1252        from sage.rings.number_field.all import is_NumberField
     1253        if not is_NumberField(L):
     1254            raise ValueError, "L (=%s) must be a NumberField in is_norm" % L
     1255        if L.degree() == 1 or self.is_zero():
     1256            return True, L(self)
     1257        d = L.polynomial().denominator()
     1258        if not d == 1:
     1259            M, M_to_L = L.subfield(L.gen()*d)
     1260            b, x = self.is_norm(M, element = True, proof = proof)
     1261            if b:
     1262                x = M_to_L(x)
     1263            return b, x
     1264        a, b = self.bnfisnorm(L, certify = proof)
     1265        if b == 1:
     1266            assert a.norm() == self
     1267            return True, a
     1268        if L.is_galois():
     1269            return False, None
     1270        M = L.galois_closure('a')
     1271        from sage.functions.log import log
     1272        from sage.functions.other import floor
     1273        extra_primes = floor(12*log(abs(M.discriminant()))**2)
     1274        a, b = self.bnfisnorm(L, certify = proof, extra_primes = extra_primes)
     1275        if b == 1:
     1276            assert a.norm() == self
     1277            return True, a
     1278        if proof:
     1279            raise NotImplementedError, "is_norm is not implemented unconditionally for norms from non-Galois number fields"
     1280        return False, None
     1281
     1282    def bnfisnorm(self, K, certify = True, extra_primes = 0):
     1283        r"""
     1284        This gives the output of the Pari function bnfisnorm.
     1285       
     1286        Tries to tell whether the rational number self is the norm of some
     1287        element y in K. Returns a pair (a, b) where self = Norm(a)*b. Looks for
     1288        a solution that is an S-unit, with S a certain set of prime ideals
     1289        containing (among others) all primes dividing self.
     1290       
     1291        If K is known to be Galois, set extra_primes = 0 (in this case, self
     1292        is a norm iff b = 1).
     1293       
     1294        If extra_primes is non-zero, the program adds to S the following
     1295        prime ideals, depending on the sign of extra_primes.
     1296        If extra_primes > 0, the ideals of norm less than extra_primes.
     1297        And if extra_primes < 0, the ideals dividing extra_primes.
     1298
     1299        Assuming GRH, the answer is guaranteed (i.e., self is a norm
     1300        iff b = 1), if S contains all primes less than 12log(\disc(L))^2,
     1301        where L is the Galois closure of K.
     1302
     1303        INPUT:
     1304       
     1305         - K -- a number field
     1306         - certify -- whether to certify the output of bnfinit.
     1307           If false, then correctness of the output depends on GRH.
     1308         - extra_primes -- an integer as explained above
     1309
     1310        OUTPUT:
     1311       
     1312        A pair (a, b) with a in K and b in `QQ` such that self == Norm(a)*b
     1313        as explained above.
     1314       
     1315        ALGORITHM:
     1316       
     1317        Uses Pari's bnfisnorm.
     1318       
     1319        EXAMPLES::
     1320       
     1321            sage: QQ(2).bnfisnorm(QuadraticField(-1, 'i'))
     1322            (i + 1, 1)
     1323            sage: 7.bnfisnorm(NumberField(x^3-2, 'b'))
     1324            (1, 7)
     1325       
     1326        AUTHORS:
     1327
     1328        - Craig Citro (2008-04-05)
     1329
     1330        - Marco Streng (2010-12-03)
     1331        """
     1332        from sage.rings.number_field.all import is_NumberField
     1333        if not is_NumberField(K):
     1334            raise ValueError, "K must be a NumberField in bnfisnorm"
     1335        if certify:
     1336            K.pari_bnf_certify()
     1337
     1338        a, b = self._pari_().bnfisnorm(K.pari_bnf(), flag = extra_primes)
     1339        deg = K.degree()
     1340        coeffs = [ a.lift().polcoeff(i)._sage_() for i in range(deg) ]
     1341        from sage.rings.rational_field import QQ
     1342        return K(coeffs), QQ(b._sage_())
     1343
     1344
    11711345    def is_perfect_power(self, expected_value=False):
    11721346        r"""
    11731347        Returns ``True`` if self is a perfect power.