# HG changeset patch
# User Craig Citro <craigcitro@gmail.com>
# Date 1261466849 28800
# Node ID faaaf3d2cbae961e7e90eee7434165bbcb98c949
# Parent  f872a92f5f9afff4b4971afc82bf9270faec269b
Fix trac #7616 -- bug in code for relative number fields of degree one.

diff -r f872a92f5f9a -r faaaf3d2cbae sage/rings/number_field/maps.py
--- a/sage/rings/number_field/maps.py	Sat Oct 24 20:06:53 2009 -0700
+++ b/sage/rings/number_field/maps.py	Mon Dec 21 23:27:29 2009 -0800
@@ -213,30 +213,83 @@
         NumberFieldIsomorphism.__init__(self, Hom(K, V))
 
     def _call_(self, alpha):
+        """
+        TESTS::
+
+            sage: K.<a> = NumberField(x^5+2)
+            sage: R.<y> = K[]
+            sage: D.<x0> = K.extension(y + a + 1) 
+            sage: D(a)
+            a
+            sage: V, from_V, to_V = D.relative_vector_space()
+            sage: to_V(a)
+            (a)
+            sage: to_V(a^3)
+            (a^3)
+            sage: to_V(x0)
+            (-a - 1)
+
+            sage: K.<a> = QuadraticField(-3)
+            sage: L.<b> = K.extension(x-5)
+            sage: L(a)
+            a
+            sage: a*b
+            5*a
+            sage: b
+            5
+            sage: V, from_V, to_V = L.relative_vector_space()
+            sage: to_V(a)
+            (a)
+        """
         # An element of a relative number field is represented
         # internally by an absolute polynomial over QQ.
         alpha = self.__K(alpha)
+        
+        # Pari doesn't return a valid relative polynomial from an
+        # absolute one in the case of relative degree one, so we work
+        # around it. (Bug submitted to Pari, fixed in svn unstable as
+        # of 1/22/08 according to Karim Belabas. Trac #1891 is a
+        # reminder to remove this workaround once we update Pari in
+        # Sage.)
+        if self.__K.relative_degree() == 1:
+            # Let K/F be our relative extension, let z be the absolute
+            # polynomial for K (which *need not* be the absolute
+            # polynomial for F!), and let pol be the relative
+            # polynomial for K/F. Then self.__rnf[10] returns a triple
+            # z, a, k, where z is as above, a is a polynomial
+            # representing the absolute generator gamma of F as a
+            # polynomial in a root of z, and k is an integer
+            # satisfying
+            #     theta = beta + k*gamma
+            # where theta is a root of z, and beta is a root of pol.
+            #
+            # Now f is a polynomial representing our element alpha as
+            # a polynomial in theta. However, we need a polynomial g
+            # representing alpha in terms of gamma, so we simply use
+            # the relation above to write theta as a polynomial in
+            # gamma, and then we can simply evaluate f at that
+            # polynomial, and this is our g. The code below does
+            # exactly this -- all the business with subst and
+            # self.__x, self.__y is there to deal with Pari's
+            # frustrating representation of relative number fields and
+            # "variable priority."
+            #
+            f = alpha._pari_().lift()
+            z, a, k = self.__rnf[10]
+            beta = -self.__rnf[0][0] / self.__rnf[0][1]
+            theta = beta + k*self.__y
+            f_in_base = f.subst(self.__x, theta).lift().subst(self.__y, self.__x)
+            return self.__V([self.__K.base_field()(f_in_base)])
+
+        # f is the absolute polynomial that defines this number field
+        # element
         f = alpha.polynomial('x')
-        # f is the absolute polynomial that defines this number field element
-        if self.__K.relative_degree() == 1:
-            # Pari doesn't return a valid relative polynomial from an
-            # absolute one in the case of relative degree one. (Bug
-            # submitted to Pari, fixed in svn unstable as of 1/22/08
-            # according to Karim Belabas. Trac #1891 is a reminder to
-            # remove this workaround once we update Pari in Sage.)
-            # However, in this case, the polynomial we want for g is
-            # just the polynomial we have for f, but as a polynomial
-            # in the generator of the base field of this relative
-            # extension. That generator is just -self.__rnf[0][0], so
-            # we can plug it in and it works.
-            g = f(-1*self.__rnf[0][0])
-        else:
-            g = self.__rnf.rnfeltabstorel(pari(f))
+        g = self.__rnf.rnfeltabstorel(pari(f))
         # Now g is a relative polynomial that defines this element.
         # This g is a polynomial in a pari variable x with
-        # coefficients polynomials in a variable y.
-        # These coefficients define the coordinates of the
-        # vector we are constructing.
+        # coefficients polynomials in a variable y.  These
+        # coefficients define the coordinates of the vector we are
+        # constructing.
         
         # The list v below has the coefficients that are the
         # components of the vector we are constructing, but each is
diff -r f872a92f5f9a -r faaaf3d2cbae sage/rings/number_field/number_field.py
--- a/sage/rings/number_field/number_field.py	Sat Oct 24 20:06:53 2009 -0700
+++ b/sage/rings/number_field/number_field.py	Mon Dec 21 23:27:29 2009 -0800
@@ -1037,6 +1037,13 @@
              Isomorphism given by variable name change map:
               From: Number Field in z with defining polynomial x^2 + 3
               To:   Number Field in a with defining polynomial x^2 + 3)
+
+            sage: K.<a> = QuadraticField(-3) 
+            sage: R.<y> = K[] 
+            sage: D.<x0> = K.extension(y) 
+            sage: D_abs.<y0> = D.absolute_field() 
+            sage: D_abs.structure()[0](y0) 
+            -a 
         """
         try:
             if self.__to_self is not None:
diff -r f872a92f5f9a -r faaaf3d2cbae sage/rings/number_field/number_field_element.pyx
--- a/sage/rings/number_field/number_field_element.pyx	Sat Oct 24 20:06:53 2009 -0700
+++ b/sage/rings/number_field/number_field_element.pyx	Mon Dec 21 23:27:29 2009 -0800
@@ -66,7 +66,7 @@
 
 from sage.modules.free_module_element import vector
 
-from sage.libs.all import pari_gen
+from sage.libs.all import pari_gen, pari
 from sage.libs.pari.gen import PariError
 from sage.structure.element cimport Element, generic_power_c
 
@@ -2629,16 +2629,9 @@
             self.__pari = {}
         if var is None:
             var = self.number_field().variable_name()
-        f = self.polynomial()._pari_()
-        gp = self.number_field().polynomial()
-        if gp.variable_name() != 'x':
-            gp = gp.change_variable_name('x')
-        g = gp._pari_()
-        gv = str(gp.parent().gen())
-        if var != 'x':
-            f = f.subst("x",var)
-        if var != gv:
-            g = g.subst(gv, var)
+
+        f = self.polynomial()._pari_().subst('x', var)
+        g = self.number_field().pari_polynomial().subst('x', var)
         h = f.Mod(g)
         self.__pari[var] = h
         return h
@@ -3028,11 +3021,9 @@
             pass
         except TypeError:
             self.__pari = {}
-        g = self.parent().pari_polynomial()
+        g = self.parent().pari_polynomial(var)
         f = self.polynomial()._pari_()
         f = f.subst('x', var)
-        g = g.subst('x', var)
-        h = f.Mod(g)
         h = f.Mod(g)
         self.__pari[var] = h
         return h
diff -r f872a92f5f9a -r faaaf3d2cbae sage/rings/number_field/number_field_rel.py
--- a/sage/rings/number_field/number_field_rel.py	Sat Oct 24 20:06:53 2009 -0700
+++ b/sage/rings/number_field/number_field_rel.py	Mon Dec 21 23:27:29 2009 -0800
@@ -185,7 +185,7 @@
     EXAMPLES::
 
         sage: K.<a> = NumberField(x^3 - 2)
-        sage: t = K['x'].gen()
+        sage: t = polygen(K)
         sage: L.<b> = K.extension(t^2+t+a); L
         Number Field in b with defining polynomial x^2 + x + a over its base field
     """
@@ -219,7 +219,7 @@
 
         A relative extension of a relative extension::
 
-            sage: x = ZZ['x'].0
+            sage: x = polygen(ZZ)
             sage: k.<a> = NumberField([x^2 + 2, x^2 + 1])
             sage: l.<b> = k.extension(x^2 + 3)
             sage: l
@@ -233,20 +233,21 @@
 
         Test that irreducibility testing is working::
 
-            sage: x = ZZ['x'].0
+            sage: x = polygen(ZZ)
             sage: K.<a, b> = NumberField([x^2 + 2, x^2 + 3])
             sage: K.<a> = NumberField(x^2 + 2)
-            sage: L.<b> = K.extension(K['x'].0^3 + 3*a)
+            sage: x = polygen(K)
+            sage: L.<b> = K.extension(x^3 + 3*a)
 
-            sage: (K['x'].0^3 + 2*a).factor()
+            sage: (x^3 + 2*a).factor()
             (x - a) * (x^2 + a*x - 2)
-            sage: L.<b> = K.extension(K['x'].0^3 + 2*a)
+            sage: L.<b> = K.extension(x^3 + 2*a)
             Traceback (most recent call last):
             ...
             ValueError: defining polynomial (x^3 + 2*a) must be irreducible
-            sage: (K['x'].0^2 + 2).factor()
+            sage: (x^2 + 2).factor()
             (x - a) * (x + a)
-            sage: L.<b> = K.extension(K['x'].0^2 + 2)
+            sage: L.<b> = K.extension(x^2 + 2)
             Traceback (most recent call last):
             ...
             ValueError: defining polynomial (x^2 + 2) must be irreducible
@@ -278,7 +279,7 @@
         # polynomial in y to satisfy PARI's ordering requirements.
 
         if base.is_relative():
-            abs_base = base.absolute_field('a')
+            abs_base = base.absolute_field(name+'0')
             from_abs_base, to_abs_base = abs_base.structure()
         else:
             abs_base = base
@@ -311,7 +312,8 @@
         self._assign_names(tuple(names), normalize=False)
         
         NumberField_generic.__init__(self, self.absolute_polynomial(), name=None,
-                                     latex_name=latex_name, check=False, embedding=embedding)
+                                     latex_name=latex_name, check=False,
+                                     embedding=embedding)
 
         v[0] = self._gen_relative()
         v = [self(x) for x in v]
@@ -642,9 +644,9 @@
 
         EXAMPLES::
 
-            sage: x = QQ['x'].0
+            sage: x = polygen(QQ)
             sage: K.<a> = NumberField(x^3 - 2)
-            sage: t = K['x'].gen()
+            sage: t = polygen(K)
             sage: K.extension(t^2+t+a, 'b')._latex_()
             '( \\Bold{Q}[a]/(a^{3} - 2) )[b]/(b^{2} + b + a)'
         """
@@ -728,8 +730,9 @@
 
         MORE EXAMPLES::
 
-            sage: K.<a> = NumberField(ZZ['x'].0^5 + 2, 'a')
-            sage: L.<b> = K.extension(ZZ['x'].0^2 + 3*a, 'b')
+            sage: x = polygen(ZZ)
+            sage: K.<a> = NumberField(x^5 + 2, 'a')
+            sage: L.<b> = K.extension(x^2 + 3*a, 'b')
             sage: u = QQ['u'].gen()
             sage: t = u.parent()['t'].gen()
 
@@ -806,25 +809,46 @@
             sage: k(m.0^4)
             9
 
-            sage: K.<a> = NumberField(ZZ['x'].0^2 + 2, 'a')
-            sage: L.<b> = K.extension(ZZ['x'].0 - a, 'b')
+            sage: x = polygen(ZZ)
+            sage: K.<a> = NumberField(x^2 + 2, 'a')
+            sage: L.<b> = K.extension(x - a, 'b')
             sage: L(a)
             a
             sage: L(b+a)
             2*a
-            sage: K.<a> = NumberField(ZZ['x'].0^5 + 2, 'a')
-            sage: L.<b> = K.extension(ZZ['x'].0 - a, 'b')
+            sage: K.<a> = NumberField(x^5 + 2, 'a')
+            sage: L.<b> = K.extension(x - a, 'b')
             sage: L(a)
             a
             sage: L(a**3)
             a^3
             sage: L(a**2+b)
             a^2 + a
-            sage: L.<b> = K.extension(ZZ['x'].0 + a/2, 'b')
+            sage: L.<b> = K.extension(x + a/2, 'b')
             sage: L(a)
             a
+            sage: L(a).polynomial()
+            -2*x
+            sage: L(a).minpoly()
+            x - a
+            sage: L(a).absolute_minpoly()
+            x^5 + 2
             sage: L(b)
             -1/2*a
+            sage: L(b).polynomial() 
+            x 
+            sage: L(b).absolute_minpoly() 
+            x^5 - 1/16 
+            sage: L(b).minpoly() 
+            x + 1/2*a 
+
+        :: 
+
+            sage: K.<a> = NumberField(x^5+2) 
+            sage: R.<y> = K[] 
+            sage: L.<x0> = K.extension(y + a**2) 
+            sage: L(a) 
+            a 
         """
         if isinstance(x, (int, long, rational.Rational,
                               integer.Integer, pari_gen,
@@ -950,14 +974,16 @@
             
     def _rnfeltreltoabs(self, element, check=False):
         r"""
-        Return PARI's ``rnfeletreltoabs()``, but without requiring ``rnfinit()``.
+        Return PARI's ``rnfeltreltoabs()``, but without requiring
+        ``rnfinit()``.
 
         TESTS::
 
-            sage: x = ZZ['x'].0
+            sage: x = polygen(ZZ)
             sage: K.<a> = NumberField(x^2 + 2)
-            sage: L.<b> = K.extension(K['x'].0^3 + 3*a)
-            sage: M.<c> = L.extension(L['x'].0^2 + 5*b)
+            sage: x = polygen(K)
+            sage: L.<b> = K.extension(x^3 + 3*a)
+            sage: M.<c> = L.extension(x^2 + 5*b)
 
             sage: L._rnfeltreltoabs(b^2 + a, check=True)
             -2/9*x^3 - 2
@@ -965,10 +991,13 @@
             1/625*x^6
         """
         z, a, k = self._pari_rnfequation()
-        # a is an alpha in extension such that z(alpha) = base_polynomial(alpha) = 0
-        # extension_polynomial(beta) = 0
-        # absolute_polynomial(theta) = 0
-        # theta = beta + k alpha
+        # If the relative extension is L/K, then z is the absolute
+        # polynomial for L, a is a polynomial giving the absolute
+        # generator alpha of K as a polynomial in a root of z, and k
+        # is a small integer such that
+        #   theta = beta + k*alpha,
+        # where theta is a root of z and beta is a root of the
+        # relative polynomial for L/K.
         pol = element.polynomial('y')
         t2 = pol(a).lift()
         if check:
@@ -1226,7 +1255,7 @@
             sage: K.base_field()
             Number Field in b with defining polynomial x^3 + 3 over its base field
             sage: K.absolute_base_field()[0]
-            Number Field in a with defining polynomial x^9 + 3*x^6 + 165*x^3 + 1
+            Number Field in a0 with defining polynomial x^9 + 3*x^6 + 165*x^3 + 1
             sage: K.base_field().absolute_field('z')
             Number Field in z with defining polynomial x^9 + 3*x^6 + 165*x^3 + 1
         """
@@ -1241,16 +1270,19 @@
         TESTS::
 
             sage: K.<a> = NumberField(x^2 + 2)
-            sage: L.<b> = K.extension(K['x'].0^5 + 2*a)
+            sage: x = polygen(K)
+            sage: L.<b> = K.extension(x^5 + 2*a)
             sage: L._pari_rnfequation()
             [x^10 + 8, Mod(-1/2*x^5, x^10 + 8), 0]
+            sage: x = polygen(ZZ)
             sage: NumberField(x^10 + 8, 'a').is_isomorphic(L)
             True
 
         Initialization is lazy enough to allow arithmetic in massive fields::
 
             sage: K.<a> = NumberField(x^10 + 2000*x + 100001)
-            sage: L.<b> = K.extension(K['x'].0^10 + 2*a)
+            sage: x = polygen(K)
+            sage: L.<b> = K.extension(x^10 + 2*a)
             sage: L._pari_rnfequation()
             [x^100 - 1024000*x^10 + 102401024, Mod(-1/2*x^10, x^100 - 1024000*x^10 + 102401024), 0]
             sage: a + b
@@ -1339,7 +1371,7 @@
 
         EXAMPLES::
 
-            sage: x = ZZ['x'].0
+            sage: x = polygen(ZZ)
             sage: K.<a, b> = NumberField([x^2 + 2, x^2 + 3]); K
             Number Field in a with defining polynomial x^2 + 2 over its base field
             sage: K.pari_absolute_base_polynomial()
@@ -1378,7 +1410,7 @@
             sage: m.<z> = k.extension(k['w']([i,0,1]))
             sage: m
             Number Field in z with defining polynomial w^2 + i over its base field
-            sage: m.pari_relative_polynomial ()
+            sage: m.pari_relative_polynomial()
             Mod(1, y^2 + 1)*x^2 + Mod(y, y^2 + 1)
 
             sage: l.<t> = m.extension(m['t'].0^2 + z)
@@ -1977,7 +2009,7 @@
 
         EXAMPLES::
 
-            sage: x = QQ['x'].0
+            sage: x = polygen(QQ)
             sage: K.<a> = NumberField(x^2 + 1)
             sage: R.<t> = PolynomialRing(K)
             sage: L = K.extension(t^5-t+a, 'b')
@@ -2001,9 +2033,10 @@
 
         EXAMPLES::
 
-            sage: x = QQ['x'].0
+            sage: x = polygen(QQ)
             sage: K.<a> = NumberField(x^2+6)
-            sage: L.<b> = K.extension(K['x'].gen()^2 + 3)    ## extend by x^2+3
+            sage: x = polygen(K)
+            sage: L.<b> = K.extension(x^2 + 3)    ## extend by x^2+3
             sage: L.is_free()
             False
         """
@@ -2020,11 +2053,10 @@
 
         EXAMPLES::
 
-            sage: x = QQ['x'].0
-            sage: K = NumberField(x^3 - 2, 'a')
-            sage: R = K['x']
-            sage: L = K.extension(R.gen()^2 - K.gen(), 'b')
-            sage: b = L.gen()
+            sage: x = polygen(ZZ)
+            sage: K.<a> = NumberField(x^3 - 2)
+            sage: R.<y> = K[]
+            sage: L.<b> = K.extension(y^2 - a)
             sage: L.lift_to_base(b^4)
             a^2
             sage: L.lift_to_base(b)
