Ticket #9541: trac_9541-part7-generic_elts.patch

File trac_9541-part7-generic_elts.patch, 40.3 KB (added by was, 7 years ago)
  • sage/rings/number_field/implementation.pyx

    # HG changeset patch
    # User William Stein <wstein@gmail.com>
    # Date 1279753987 -7200
    # Node ID 53c4551ed34f4ee655eb78c0b9c87fb3c45a9d51
    # Parent  f09d5a19ec34645612cc112d30fa735cc7b77aa0
    [mq]: trac_9541-part7-generic_elts.patch
    
    diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/implementation.pyx
    a b  
    8080        """
    8181        return cmp(self.name(), right.name())
    8282
     83    def use_absolute_polynomials(self):
     84        """
     85        Returns True if in this implementation elements of a relative
     86        extension are represented using an absolute polynomial.
     87
     88        EXAMPLES::
     89
     90             sage: sage.rings.number_field.implementation.ArithmeticImplementation('test').use_absolute_polynomials()
     91             False
     92        """
     93        return False
     94
    8395cdef class ArithmeticImplementation_generic(ArithmeticImplementation):
    8496    def __init__(self, modulus):
    8597        """
     
    101113        """
    102114        return self.__class__, (self.modulus, )
    103115
     116    def use_absolute_polynomials(self):
     117        """
     118        Returns True if in this implementation elements of a relative
     119        extension are represented using an absolute polynomial.
     120
     121        EXAMPLES::
     122
     123            sage: A = sage.rings.number_field.implementation.ArithmeticImplementation_generic(x^2 + 3)
     124            sage: A.use_absolute_polynomials()
     125            False
     126        """
     127        return False
     128
    104129cdef class ArithmeticImplementation_ntl(ArithmeticImplementation):
    105130    def __init__(self):
    106131        """
     
    111136        """
    112137        ArithmeticImplementation.__init__(self, 'ntl')
    113138
     139    def use_absolute_polynomials(self):
     140        """
     141        Returns True if in this implementation elements of a relative
     142        extension are represented using an absolute polynomial.
     143
     144        EXAMPLES::
     145
     146            sage: sage.rings.number_field.implementation.ArithmeticImplementation_ntl().use_absolute_polynomials()
     147            True
     148        """
     149        return True
     150
    114151cdef class ArithmeticImplementation_flint(ArithmeticImplementation):
    115152    def __init__(self, modulus):
    116153        """
     
    128165    def __dealloc__(self):
    129166        fmpq_poly_clear(self.modulus)
    130167       
     168    def use_absolute_polynomials(self):
     169        """
     170        Returns True if in this implementation elements of a relative
     171        extension are represented using an absolute polynomial.
     172
     173        EXAMPLES::
     174
     175            sage: R.<x> = QQ[]
     176            sage: sage.rings.number_field.implementation.ArithmeticImplementation_flint(x-1).use_absolute_polynomials()
     177            True
     178        """
     179        return True
    131180
    132181cdef class ArithmeticImplementation_singular(ArithmeticImplementation):
    133182    def __init__(self):
  • sage/rings/number_field/maps.py

    diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/maps.py
    a b  
    262262
    263263    def _call_(self, v):
    264264        """
    265         INPUT::
    266 
    267            - `v` -- element
     265        INPUT:
     266            - `v` -- element
    268267           
    269268        EXAMPLES::
    270269
    271             sage: K.<a,b> = NumberField([x^3+2,x^2-2]); phi = K.relative_vector_space()[1]
     270            sage: K.<a,b> = NumberField([x^3 + 7, x^3 + 2], implementation='generic')
     271            sage: V,f,t = K.relative_vector_space()
     272            sage: [f(z) for z in V.basis()]
     273            [1, a, a^2]
     274       
     275            sage: K.<a,b> = NumberField([x^3+2, x^2-2]); phi = K.relative_vector_space()[1]
    272276            sage: V = phi.domain(); phi(V.0 + 3*V.1)
    273277            3*a + 1
    274278        """
    275         # Given a relative vector space element, we have to
    276         # compute the corresponding number field element, in terms
     279        # Given a relative vector space element, this function
     280        # computes the corresponding number field element, in terms
    277281        # of an absolute generator.
    278282        w = self.__V(v).list()
     283       
     284        if self.__K.implementation().use_absolute_polynomials():
    279285
    280         # First, construct from w a PARI polynomial in x with coefficients
    281         # that are polynomials in y:
    282         B = self.__B
    283         _, to_B = B.structure()
    284         # Apply to_B, so now each coefficient is in an absolute field,
    285         # and is expressed in terms of a polynomial in y, then make
    286         # the PARI poly in x.
    287         w = [pari(to_B(a).polynomial('y')) for a in w]
    288         h = pari(w).Polrev()
     286            # First, construct from w a PARI polynomial in x with coefficients
     287            # that are polynomials in y:
     288            B = self.__B
     289            _, to_B = B.structure()
    289290
    290         # Next we write the poly in x over a poly in y in terms
    291         # of an absolute polynomial for the rnf.
    292         g = self.__R(self.__rnf.rnfeltreltoabs(h))
    293         return self.__K._element_class(self.__K, g)
     291            # Apply to_B, so now each coefficient is in an absolute field,
     292            # and is expressed in terms of a polynomial in y, then make
     293            # the PARI poly in x.
     294            w = [pari(to_B(a).polynomial('y')) for a in w]
     295            h = pari(w).Polrev()
     296
     297            # Next we write the poly in x over a poly in y in terms
     298            # of an absolute polynomial for the rnf.
     299            g = self.__R(self.__rnf.rnfeltreltoabs(h))
     300            return self.__K._element_class(self.__K, g)
     301       
     302        else:
     303           
     304            # much easier case
     305            return self.__K._element_class(self.__K, w)
    294306
    295307class MapRelativeNumberFieldToRelativeVectorSpace(NumberFieldIsomorphism):
    296308    def __init__(self, K, V):
     
    318330        """
    319331        TESTS::
    320332
    321             sage: K.<a> = NumberField(x^5+2)
     333            sage: K.<a,b> = NumberField([x^3 + 7, x^3 + 2], implementation='generic')
     334            sage: V,f,t = K.relative_vector_space()
     335            sage: t(a)
     336            (0, 1, 0)
     337            sage: t(b)
     338            (b, 0, 0)
     339            sage: t(a^2*b + a - 3/4)
     340            (-3/4, 1, b)
     341
     342        The ntl implementation tests the code in the case when
     343        everything is represented using an absolute polynomial::
     344       
     345            sage: K.<a> = NumberField(x^5+2, implementation='ntl')
    322346            sage: R.<y> = K[]
    323347            sage: D.<x0> = K.extension(y + a + 1)
    324348            sage: D(a)
     
    344368            (a)
    345369        """
    346370        # An element of a relative number field is represented
    347         # internally by an absolute polynomial over QQ.
     371        # internally by either a relative or absolute polynomial over QQ.
     372       
    348373        alpha = self.__K(alpha)
     374
     375        if not self.__K.implementation().use_absolute_polynomials():
     376           
     377            return self.__V(alpha.relative_polynomial().padded_list(self.__K.relative_degree()))
    349378       
    350         # Pari doesn't return a valid relative polynomial from an
    351         # absolute one in the case of relative degree one, so we work
    352         # around it. (Bug submitted to Pari, fixed in svn unstable as
    353         # of 1/22/08 according to Karim Belabas. Trac #1891 is a
    354         # reminder to remove this workaround once we update Pari in
    355         # Sage.)
    356         if self.__K.relative_degree() == 1:
    357             # Let K/F be our relative extension, let z be the absolute
    358             # polynomial for K (which *need not* be the absolute
    359             # polynomial for F!), and let pol be the relative
    360             # polynomial for K/F. Then self.__rnf[10] returns a triple
    361             # z, a, k, where z is as above, a is a polynomial
    362             # representing the absolute generator gamma of F as a
    363             # polynomial in a root of z, and k is an integer
    364             # satisfying
    365             #     theta = beta + k*gamma
    366             # where theta is a root of z, and beta is a root of pol.
     379        else:
     380            # The case of an absolute polynomial...
    367381            #
    368             # Now f is a polynomial representing our element alpha as
    369             # a polynomial in theta. However, we need a polynomial g
    370             # representing alpha in terms of gamma, so we simply use
    371             # the relation above to write theta as a polynomial in
    372             # gamma, and then we can simply evaluate f at that
    373             # polynomial, and this is our g. The code below does
    374             # exactly this -- all the business with subst and
    375             # self.__x, self.__y is there to deal with Pari's
    376             # frustrating representation of relative number fields and
    377             # "variable priority."
    378             #
    379             f = alpha._pari_().lift()
    380             z, a, k = self.__rnf[10]
    381             beta = -self.__rnf[0][0] / self.__rnf[0][1]
    382             theta = beta + k*self.__y
    383             f_in_base = f.subst(self.__x, theta).lift().subst(self.__y, self.__x)
    384             return self.__V([self.__K.base_field()(f_in_base)])
     382            # Pari doesn't return a valid relative polynomial from an
     383            # absolute one in the case of relative degree one, so we work
     384            # around it. (Bug submitted to Pari, fixed in svn unstable as
     385            # of 1/22/08 according to Karim Belabas. Trac #1891 is a
     386            # reminder to remove this workaround once we update Pari in
     387            # Sage.)
     388            if self.__K.relative_degree() == 1:
     389                # Let K/F be our relative extension, let z be the absolute
     390                # polynomial for K (which *need not* be the absolute
     391                # polynomial for F!), and let pol be the relative
     392                # polynomial for K/F. Then self.__rnf[10] returns a triple
     393                # z, a, k, where z is as above, a is a polynomial
     394                # representing the absolute generator gamma of F as a
     395                # polynomial in a root of z, and k is an integer
     396                # satisfying
     397                #     theta = beta + k*gamma
     398                # where theta is a root of z, and beta is a root of pol.
     399                #
     400                # Now f is a polynomial representing our element alpha as
     401                # a polynomial in theta. However, we need a polynomial g
     402                # representing alpha in terms of gamma, so we simply use
     403                # the relation above to write theta as a polynomial in
     404                # gamma, and then we can simply evaluate f at that
     405                # polynomial, and this is our g. The code below does
     406                # exactly this -- all the business with subst and
     407                # self.__x, self.__y is there to deal with Pari's
     408                # frustrating representation of relative number fields and
     409                # "variable priority."
     410                #
     411                f = alpha._pari_().lift()
     412                z, a, k = self.__rnf[10]
     413                beta = -self.__rnf[0][0] / self.__rnf[0][1]
     414                theta = beta + k*self.__y
     415                f_in_base = f.subst(self.__x, theta).lift().subst(self.__y, self.__x)
     416                return self.__V([self.__K.base_field()(f_in_base)])
    385417
    386         # f is the absolute polynomial that defines this number field
    387         # element
    388         f = alpha.polynomial('x')
    389         g = self.__rnf.rnfeltabstorel(pari(f))
    390         # Now g is a relative polynomial that defines this element.
    391         # This g is a polynomial in a pari variable x with
    392         # coefficients polynomials in a variable y.  These
    393         # coefficients define the coordinates of the vector we are
    394         # constructing.
    395        
    396         # The list v below has the coefficients that are the
    397         # components of the vector we are constructing, but each is
    398         # converted into polynomials in a variable x, which we will
    399         # use to define elements of the base field.
    400         (x, y) = (self.__x, self.__y)
    401         v = [g.polcoeff(i).subst(x,y) for i in range(self.__n)]
    402         B,from_B, _ = self.__B
    403         w = [from_B(B(z)) for z in v]
     418            # f is the absolute polynomial that defines this number field
     419            # element
     420            f = alpha.polynomial('x')
     421            g = self.__rnf.rnfeltabstorel(pari(f))
     422            # Now g is a relative polynomial that defines this element.
     423            # This g is a polynomial in a pari variable x with
     424            # coefficients polynomials in a variable y.  These
     425            # coefficients define the coordinates of the vector we are
     426            # constructing.
    404427
    405         # Now w gives the coefficients.
    406         return self.__V(w)
     428            # The list v below has the coefficients that are the
     429            # components of the vector we are constructing, but each is
     430            # converted into polynomials in a variable x, which we will
     431            # use to define elements of the base field.
     432            (x, y) = (self.__x, self.__y)
     433            v = [g.polcoeff(i).subst(x,y) for i in range(self.__n)]
     434            B,from_B, _ = self.__B
     435            w = [from_B(B(z)) for z in v]
     436
     437            # Now w gives the coefficients.
     438            return self.__V(w)
    407439
    408440
    409441class IdentityMap(NumberFieldIsomorphism):
     
    492524    EXAMPLES::
    493525   
    494526        sage: K.<a> = NumberField(x^6 + 4*x^2 + 200)
    495         sage: L = K.relativize(K.subfields(3)[0][1], 'b'); L
    496         Number Field in b0 with defining polynomial x^2 + a0 over its base field
     527        sage: L = K.relativize(K.subfields(3)[0][1], 'b')
    497528        sage: fr, to = L.structure()
    498529        sage: fr
    499530        Relative number field morphism:
     
    553584        """
    554585        EXAMPLES::
    555586       
    556             sage: K.<a,b> = NumberField([x^2+1,x^2+3]); L.<c> = K.absolute_field(); phi = L.structure()[1]
     587            sage: K.<a,b> = NumberField([x^2+1, x^2+3]); L.<c> = K.absolute_field(); phi = L.structure()[1]
    557588            sage: phi(a+b)
    558589            -1/2*c^3 - 4*c
    559590            sage: L.structure()[0](phi(a+b))
     
    562593            2/3
    563594            sage: phi(2/3).parent()
    564595            Number Field in c with defining polynomial x^4 + 8*x^2 + 4
     596       
     597            sage: K.<a,b> = NumberField([x^3+2,x^3+3])
     598            sage: L.<c> = K.absolute_field()
     599            sage: phi = L.structure()[1]
     600            sage: phi(a)
     601            -2/45*c^7 + 7/45*c^4 - 311/45*c
     602            sage: phi(b)
     603            -2/45*c^7 + 7/45*c^4 - 356/45*c
     604            sage: phi(a).minpoly()
     605            x^3 + 2
     606            sage: phi(b).minpoly()
     607            x^3 + 3
    565608        """
    566         f = self.__R(x).polynomial()
     609        f = self.__R(x).absolute_polynomial('x')
    567610        return self.__A._element_class(self.__A, f)
    568611   
    569612class MapAbsoluteToRelativeNumberField(NumberFieldIsomorphism):
  • sage/rings/number_field/number_field.py

    diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/number_field.py
    a b  
    249249from sage.rings.real_lazy import RLF, CLF
    250250
    251251
     252# Use this dictionary to set the default implementation for relative
     253# and absolute number fields.  Choices include:
     254#      - 'ntl'
     255#      - 'flint'
     256#      - 'generic'
     257#      - 'singular'
     258#DEFAULT_IMPLEMENTATION = {'relative':'generic', 'absolute':'generic'}
     259DEFAULT_IMPLEMENTATION = {'relative':'ntl', 'absolute':'ntl'}
     260
    252261_nf_cache = {}
    253262def NumberField(polynomial, name=None, check=True, names=None, cache=True,
    254263                embedding=None, latex_name=None,
     
    477486        if polynomial.degree() == 2 and polynomial.base_ring() == QQ:
    478487            implementation = 'quadratic'
    479488        else:
    480             implementation = 'ntl'
     489            implementation = DEFAULT_IMPLEMENTATION['absolute']
    481490
    482491    if cache:
    483492        key = (polynomial, polynomial.base_ring(), name, latex_name,
     
    48274836            self._order_element_class = number_field_element_generic.OrderElement_generic
    48284837            self._set_implementation(arithmetic_implementation.ArithmeticImplementation_generic(polynomial))
    48294838        else:
    4830             raise ValueError, "unknown implementation '%s'"%implementation
     4839            raise ValueError, "invalid number field implementation '%s'"%implementation
    48314840       
    48324841        assert self.implementation() is not None
    48334842       
     
    53135322            a = self(elts[i])
    53145323            if self.coerce_embedding() is not None:
    53155324                embedding = self.coerce_embedding()(a)
    5316             K = NumberField(f, names=name + str(i), embedding=embedding)
     5325            K = NumberField(f, names=name + str(i), embedding=embedding, implementation=self.implementation().name())
    53175326
    53185327            from_K = K.hom([a])    # check=False here ??   would be safe unless there are bugs.
    53195328
     
    73467355       
    73477356            sage: K.<a> = NumberField(x^2 + 17); type(a)
    73487357            <type 'sage.rings.number_field.number_field_element_quadratic.NumberFieldElement_quadratic'>
    7349             sage: K.<a> = NumberField(x^2 + 17, implementation='generic'); type(a)
    7350             <type 'sage.rings.number_field.number_field_element_generic.NumberFieldElement_generic'>
    7351             sage: K.<a> = NumberField(x^2 + 17, implementation='flint'); type(a)
    7352             <type 'sage.rings.number_field.number_field_element_flint.NumberFieldElement_flint'>
    7353             sage: K.<a> = NumberField(x^2 + 17, implementation='ntl'); type(a)
    7354             <type 'sage.rings.number_field.number_field_element_ntl.NumberFieldElement_ntl_absolute'>
    7355         """
     7358        """
     7359        # Only 'quadratic' is supported for this field -- get segfaults otherwise, which
     7360        # I don't yet have time to fully debug.
     7361        implementation = 'quadratic'
    73567362        NumberField_absolute.__init__(self, polynomial, name=name, check=check, embedding=embedding,
    73577363                                      latex_name=latex_name, implementation=implementation)
    73587364       
  • sage/rings/number_field/number_field_element.pyx

    diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/number_field_element.pyx
    a b  
    296296            # Compute representation of self in terms of relative vector space.
    297297            return self.relative_polynomial()._repr(K.variable_name())
    298298
     299    def absolute_polynomial(self, var=None):
     300        """
     301        Return polynomial that represents self in terms of the
     302        isomorphic absolute extension.
     303       
     304        EXAMPLES::
     305
     306            sage: K.<a> = NumberField(x^6 + 4*x^2 + 200); a.absolute_polynomial()
     307            x
     308            sage: L.<b,b2> = K.relativize(K.subfields(3)[0][1])
     309            sage: b.absolute_polynomial()
     310            x
     311        """
     312        if self.is_absolute():
     313            return self.polynomial(var)
     314        else:
     315            if self._parent.implementation().use_absolute_polynomials():
     316                return self.polynomial(var)
     317            else:
     318                return self._parent.absolute_field('z').structure()[1](self).polynomial(var)
     319
    299320    def relative_polynomial(self, var=None):
    300321        """
    301322        Return the polynomial in var (default: 'x') over the base
     
    404425       
    405426        ::
    406427       
    407             sage: y = QQ['y'].gen()
     428            sage: R.<y> = QQ[]
    408429            sage: k.<j> = NumberField(y^3 - 2)
    409430            sage: pari(j)
    410431            Mod(x, x^3 - 2)
     
    442463       
    443464        ::
    444465       
    445             sage: y = QQ['y'].gen()
     466            sage: R.<y> = QQ[]
    446467            sage: k.<j> = NumberField([y^2 - 7, y^3 - 2])
    447468            sage: pari(j)
    448469            Mod(42/5515*x^5 - 9/11030*x^4 - 196/1103*x^3 + 273/5515*x^2 + 10281/5515*x + 4459/11030, x^6 - 21*x^4 + 4*x^3 + 147*x^2 + 84*x - 339)
     
    498519        if var is None:
    499520            var = self.number_field().variable_name()
    500521        if self.is_absolute():
    501             f = self.polynomial()._pari_().subst('x', var)
     522            f = self.polynomial('x')._pari_().subst('x', var)
    502523            g = self.number_field().pari_polynomial().subst('x', var)
    503524            h = f.Mod(g)
    504525            self.__pari[var] = h
    505526            return h
    506527        else:
    507528            g = self.parent().pari_polynomial(var)
    508             f = self.polynomial()._pari_()
     529            f = self.absolute_polynomial('x')._pari_()
    509530            f = f.subst('x', var)
    510531            h = f.Mod(g)
    511532            self.__pari[var] = h
    512533            return h
    513534           
    514            
    515 
    516535    def _pari_init_(self, var='x'):
    517536        """
    518537        Return GP/PARI string representation of self. This is used for
  • sage/rings/number_field/number_field_element_generic.pyx

    diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/number_field_element_generic.pyx
    a b  
    6060            <type 'sage.rings.number_field.number_field_element_generic.NumberFieldElement_generic'>
    6161            sage: a.is_absolute()
    6262            True
     63
     64            sage: K.<a> = NumberField(x^6 + 4*x^2 + 200)
     65            sage: L.<b,b2> = K.relativize(K.subfields(3)[0][1])
     66            sage: b.is_absolute()
     67            False
    6368        """
    6469        return self._parent.is_absolute()
    6570   
     
    8186            self._f = (<NumberFieldElement_generic>f)._f
    8287        else:
    8388            self._f = parent.polynomial_ring()(f)
     89            g = self.modulus()
     90            if self._f.degree() >= g.degree():
     91                self._f = self._f % g
     92
     93    def __copy__(self):
     94        """
     95        EXAMPLES::
     96       
     97            sage: K.<a> = NumberField(x^5 + 5); L.<c> = K.absolute_field()
     98            sage: c.__copy__()
     99            c
     100            sage: t = L.maximal_order().1; t
     101            c
     102            sage: t.__copy__()
     103            c
     104            sage: type(t.__copy__())
     105            <type 'sage.rings.number_field.number_field_element_generic.OrderElement_generic'>
     106            sage: type(c.__copy__())
     107            <type 'sage.rings.number_field.number_field_element_generic.NumberFieldElement_generic'>
     108            sage: t.__copy__().parent()
     109            Maximal Order in Number Field in c with defining polynomial x^5 + 5
     110            sage: c.__copy__().parent()
     111            Number Field in c with defining polynomial x^5 + 5
     112        """
     113        return self._new(self._f)
    84114
    85115    cdef _new(self, f):
    86116        cdef NumberFieldElement_generic x = PY_NEW(NumberFieldElement_generic)
     
    89119        return x
    90120
    91121    cdef void _randomize(self, num_bound, den_bound, distribution):
    92         raise NotImplementedError
     122        K = self._parent.base_field()
     123        v = [K.random_element(num_bound, den_bound, distribution) for i in self._parent.degree()]
     124        f = self._parent.polynomial_ring()(v)
     125        self._f = f
     126
     127    def relative_polynomial(self, var=None):
     128        """
     129        Return the relative polynomial that defines self.
     130
     131        For elements with the generic representation, this is the same as self.polynomial().
     132
     133        EXAMPLES::
     134
     135            sage: K.<a,b> = NumberField([x^3+7, x^3 + 2], implementation='generic')
     136            sage: a.relative_polynomial()
     137            x
     138            sage: (a+3).relative_polynomial('T')
     139            T + 3
     140            sage: (2/3*a^2+3).relative_polynomial('T')
     141            2/3*T^2 + 3
     142            sage: (a^2 + 2*b + 3/4).relative_polynomial()
     143            x^2 + 2*b + 3/4
     144        """
     145        return self.polynomial(var=var)
    93146
    94147    def polynomial(self, var=None):
    95148        """
    96149        Return polynomial representative for this number field element, in the variable x.
     150
     151        For elements with the generic representation, this is the same as self.relative_polynomial().
    97152       
    98153        EXAMPLES::
    99154
  • sage/rings/number_field/number_field_element_quadratic.pyx

    diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/number_field_element_quadratic.pyx
    a b  
    55computations in quadratic extensions of `\QQ`.
    66
    77AUTHORS:
    8 
    9 - Robert Bradshaw (2007-09): Initial version
    10 - David Harvey (2007-10): fix up a few bugs, polish around the edges
    11 - David Loeffler (2009-05): add more documentation and tests
     8    - Robert Bradshaw (2007-09): Initial version
     9    - David Harvey (2007-10): fix up a few bugs, polish around the edges
     10    - David Loeffler (2009-05): add more documentation and tests
    1211
    1312TODO:
    1413
  • sage/rings/number_field/number_field_rel.py

    diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/number_field_rel.py
    a b  
    33
    44AUTHORS:
    55
    6 - William Stein (2004, 2005): initial version
    7 - Steven Sivek (2006-05-12): added support for relative extensions
    8 - William Stein (2007-09-04): major rewrite and documentation
    9 - Robert Bradshaw (2008-10): specified embeddings into ambient fields
    10 - Nick Alexander (2009-01): modernize coercion implementation
     6    - William Stein (2004, 2005): initial version
     7    - Steven Sivek (2006-05-12): added support for relative extensions
     8    - William Stein (2007-09-04): major rewrite and documentation
     9    - Robert Bradshaw (2008-10): specified embeddings into ambient fields
     10    - Nick Alexander (2009-01): modernize coercion implementation
    1111
    1212This example follows one in the Magma reference manual::
    1313
     
    150150from sage.rings.complex_double import CDF
    151151from sage.rings.real_lazy import RLF, CLF
    152152
    153 # from sage.rings.number_field.number_field import is_AbsoluteNumberField
    154 # from sage.rings.number_field.number_field import is_QuadraticField
    155 # from sage.rings.number_field.number_field import is_CyclotomicField
     153import number_field
     154
    156155
    157156def is_RelativeNumberField(x):
    158157    r"""
     
    258257            ...
    259258            ValueError: defining polynomial (x^2 + 2) must be irreducible
    260259        """
     260        #########################################
     261        # Check preconditions
     262        #########################################       
    261263        if embedding is not None:
    262264            raise NotImplementedError, "Embeddings not implemented for relative number fields"
    263265        if not names is None: name = names
     
    272274            raise ValueError, "Base field and extension cannot have the same name"
    273275        if polynomial.parent().base_ring() != base:
    274276            polynomial = polynomial.change_ring(base)
    275             #raise ValueError, "The polynomial must be defined over the base field"
    276277
    277         # Generate the nf and bnf corresponding to the base field
    278         # defined as polynomials in y, e.g. for rnfisfree
    279 
    280         # Convert the polynomial defining the base field into a
    281         # polynomial in y to satisfy PARI's ordering requirements.
    282 
    283         if base.is_relative():
    284             abs_base = base.absolute_field(name+'0')
    285             from_abs_base, to_abs_base = abs_base.structure()
    286         else:
    287             abs_base = base
    288             from_abs_base = maps.IdentityMap(base)
    289             to_abs_base = maps.IdentityMap(base)
    290        
    291         self.__absolute_base_field = abs_base, from_abs_base, to_abs_base
    292         self.__base_field = base
    293         self.__relative_polynomial = polynomial
    294 
     278        #########################################
     279        # Set the implementation object
     280        #########################################       
    295281        if implementation == 'default':
    296             implementation = 'ntl'
    297 
     282            implementation = number_field.DEFAULT_IMPLEMENTATION['relative']
     283           
    298284        if implementation == 'ntl':
    299285            import number_field_element_ntl
    300286            self._element_class = number_field_element_ntl.NumberFieldElement_ntl_relative
     
    309295            import number_field_element_singular
    310296            self._element_class = number_field_element_singular.NumberFieldElement_singular
    311297            self._order_element_class = number_field_element_singular.OrderElement_singular
    312             self._set_implementation(arithmetic_implementation.ArithmeticImplementation_singular())            
     298            self._set_implementation(arithmetic_implementation.ArithmeticImplementation_singular())
    313299        else:
    314             raise ValueError, "unknown implementation '%s'"%implementation
    315 
     300            raise ValueError, "invalid relative number field implementation '%s'"%implementation
    316301        assert self.implementation() is not None
    317302
     303        ##################################################################################
     304        # Compute the absolute field isomorphic to the base field, which we must do since
     305        # PARI can *only* deal with 2-step towers of number fields.
     306        ##################################################################################       
     307
     308        # Generate the nf and bnf corresponding to the base field
     309        # defined as polynomials in y, e.g. for rnfisfree.
     310        # We also convert the polynomial defining the base field into a
     311        # polynomial in y to satisfy PARI's ordering requirements.
     312        if base.is_relative():
     313            abs_base = base.absolute_field(name+'0')
     314            from_abs_base, to_abs_base = abs_base.structure()
     315        else:
     316            abs_base = base
     317            from_abs_base = maps.IdentityMap(base)
     318            to_abs_base = maps.IdentityMap(base)
     319        self.__absolute_base_field = abs_base, from_abs_base, to_abs_base
     320        self.__base_field = base
     321        self.__relative_polynomial = polynomial
     322
     323        # Check that defining polynomial for this field is irreducible.
    318324        if check:
    319325            if not self.pari_relative_polynomial().polisirreducible():
    320326                # this is *much* faster than
    321                 # polynomial.is_irreducible() at some point in the
     327                # polynomial.is_irreducible(); at some point in the
    322328                # future, is_irreducible should be made faster for
    323329                # polynomials over number fields -- see ticket #4724
    324330                raise ValueError, "defining polynomial (%s) must be irreducible"%polynomial
    325331
     332        #########################################
     333        # Compute the generators of this field,
     334        # going down the tower and coercing in
     335        # each generator.
     336        #########################################       
    326337        self.__gens = [None]
    327        
    328338        v = [None]
    329339        K = base
    330340        names = [name]
     
    333343            v.append(K.gen())
    334344            K = K.base_field()
    335345
     346        #########################################
     347        # Generic initialization
     348        #########################################       
    336349        self._assign_names(tuple(names), normalize=False)
    337        
    338350        NumberField_generic.__init__(self, self.absolute_polynomial(), name=None,
    339351                                     latex_name=latex_name, check=False,
    340352                                     embedding=embedding)
    341353
     354        #########################################
     355        # Now we can finish our gens initialization
     356        #########################################       
    342357        v[0] = self._gen_relative()
    343358        v = [self(x) for x in v]
    344359        self.__gens = tuple(v)
     
    785800        """
    786801        if x.parent() is self.base_ring() or x.parent() == self.base_ring():
    787802            return self.__base_inclusion(x)
    788 
    789803        f = x.polynomial()
    790804        if f.degree() <= 0:
    791805            return self._element_class(self, f[0])
     
    11451159            sage: K._coerce_(K.base_field().0)^2
    11461160            -3
    11471161        """
    1148         abs_base, from_abs_base, to_abs_base = self.absolute_base_field()
    1149         # Write element in terms of the absolute base field
    1150         element = self.base_field().coerce(element)
    1151         element = to_abs_base(element)
    1152         # Find an expression in terms of the absolute generator for self of element.
    1153         expr_x = self._rnfeltreltoabs(element)
    1154         # Convert to a Sage polynomial, then to one in gen(), and return it
    11551162        R = self.polynomial_ring()
    1156         # We do NOT call self(...) because this code is called by
    1157         # __init__ before we initialize self.gens(), and self(...)
    1158         # uses self.gens()
    1159         return self._element_class(self, R(expr_x))
     1163        if self.implementation().use_absolute_polynomials():
     1164            abs_base, from_abs_base, to_abs_base = self.absolute_base_field()
     1165            # Write element in terms of the absolute base field
     1166            element = self.base_field().coerce(element)
     1167            element = to_abs_base(element)
     1168            # Find an expression in terms of the absolute generator for self of element.
     1169            expr_x = self._rnfeltreltoabs(element)
     1170            # Convert to a Sage polynomial, then to one in gen(), and return it
     1171            # We do NOT call self(...) because this code is called by
     1172            # __init__ before we initialize self.gens(), and self(...)
     1173            # uses self.gens()
     1174            return self._element_class(self, R(expr_x))
     1175        else:
     1176            return self._element_class(self, R(element))
    11601177
    11611178    def _fractional_ideal_class_(self):
    11621179        """
     
    14261443            sage: c^2 + 3
    14271444            0
    14281445        """
     1446        if self.implementation().use_absolute_polynomials():
     1447            f = self._absolute_pari_polynomial()
     1448        else:
     1449            f = self.polynomial_ring().gen()
     1450        return self._element_class(self, f)
     1451
     1452    @cached_method
     1453    def _absolute_pari_polynomial(self):
     1454        """
     1455        Return polynomial that the generator of self satisfies, in
     1456        terms of some choice of defining polynomial for the absolute
     1457        extension.
     1458
     1459       
     1460        EXAMPLES::
     1461
     1462            sage: K.<a,b> = NumberField([x^3+7, x^3 + 2], implementation='generic')
     1463            sage: f = K._absolute_pari_polynomial(); f
     1464            2/405*x^7 + 7/81*x^4 + 1196/405*x
     1465            sage: type(f)
     1466            <type 'sage.libs.pari.gen.gen'>
     1467            sage: pari('polcompositum(x^3+7, x^3 + 2)')
     1468            [x^9 - 15*x^6 + 453*x^3 - 125]
     1469            sage: pari('Mod(2/405*x^7 + 7/81*x^4 + 1196/405*x, x^9 + 15*x^6 + 453*x^3 + 125)^3')
     1470            Mod(-7, x^9 + 15*x^6 + 453*x^3 + 125)
     1471        """
    14291472        rnfeqn = self._pari_rnfequation()
    1430         f = (pari('x') - rnfeqn[2]*rnfeqn[1]).lift()
    1431         g = self._element_class(self, f)
    1432         return g
     1473        return (pari('x') - rnfeqn[2]*rnfeqn[1]).lift()
    14331474
    14341475    def pari_polynomial(self, name='x'):
    14351476        """
  • sage/rings/number_field/order.py

    diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/order.py
    a b  
    4242from sage.structure.element import is_Element
    4343
    4444#TODO: fix this
    45 from number_field_element_ntl import OrderElement_ntl_absolute, OrderElement_ntl_relative
     45from number_field_element_ntl import OrderElement_ntl_relative
    4646
    4747from number_field_element_quadratic import OrderElement_quadratic
    4848
     
    13781378        abs_order = self._absolute_order
    13791379        to_abs = abs_order._K.structure()[1]
    13801380        x = abs_order(to_abs(x)) # will test membership
    1381         return OrderElement_ntl_relative(self, x)
     1381        return self.number_field()._order_element_class(self, x)
    13821382
    13831383    def _repr_(self):
    13841384        """
     
    14851485        O = self._absolute_order
    14861486        K = O.number_field()
    14871487        from_K, _ = K.structure()
    1488         self.__basis = [OrderElement_ntl_relative(self, from_K(a)) for a in O.basis()]
     1488        self.__basis = [self.number_field()._order_element_class(self, from_K(a)) for
     1489                        a in O.basis()]
    14891490        return self.__basis
    14901491
    14911492    def __add__(left, right):
  • sage/rings/number_field/todo.txt

    diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/todo.txt
    a b  
    3131
    3232   [x] flint elements
    3333   [x] implement OrderElement_flint
    34 
    35    [ ] rewrite order elements to use implementation, e.g., this line in order.py:
     34   [x] rewrite order elements to use implementation, e.g., this line in order.py:
    3635       #TODO: fix this
    3736       from number_field_element_ntl import OrderElement_absolute, OrderElement_relative
     37   [x] stabilize ntl-based code
     38   [x] make sure the _cmp_c_impl's are compatible across number field element implementations.
     39   [x] make default implementation computation be centralized somehow??
    3840
     41   [ ] libsingular elements
    3942   [ ] implement OrderElement_singular
    4043
    41    [ ] generic: get to work in the *relative case*
     44   [ ] write general implementation of algorithm for computing absolute_field
     45       [ ] find random element
     46       [ ] compute charpoly
     47       [ ] if irred and squarefree, it gens
     48       [ ] do linear algebra to write everything in terms of that elements
     49       [ ] setup maps:
     50       this class MapRelativeToAbsoluteNumberField in maps.py maybe has to change
    4251
    43    [ ] libsingular elements
     52   [ ] rewrite base class "def _lift_cyclotomic_element(self, new_parent, bint check=True, int rel=0):"
     53   [ ] fix unpickling of old nf elts
    4454
    4555   [ ] get implementation = 'generic' to fully work as another default type
    46 
    47    [ ] move data out of elements into implementation objects for ntl and quadratic types
    48 
    49    [ ] fix all INPUT block list formatting
    50 
    51    [ ] rewrite base class "def _lift_cyclotomic_element(self, new_parent, bint check=True, int rel=0):"
    52 
    53    [ ] make default implementation computation be centralized somehow??
    54 
    55    [ ] fix unpickling of old nf elts
    56 
    57    [ ] change number_field_element_quadratic to derive from
    58        number_field_element code (i.e., the abstract base), instead of
    59        deriving from number_field_element_ntl.
    60 
    61    [ ] write generic ver    def _lift_cyclotomic_element(self, new_parent, bint check=True, int rel=0):
    62        of this in number_field_element.pyx
    63 
    64    [ ] make sure the _cmp_c_impl's are compatible across number field element implementations.
    65 
    66    [ ] format all documentation perfectly
    67 
    6856   [ ] make the implementation part of elements into a cython class hierarchy with
    6957       [ ] implementation object needs to get pickled with number field -- test
    7058       [ ] flint implementation object
    7159       [ ] libsingular implementation object
     60   [ ] benchmark for comparison with magma
     61   [ ] get doctest coverage to 100% for the number_field directory
    7262
    73    [ ] benchmark *every single operation* with each type of elements... for sanity
    74    [ ] benchmark for comparison with magma
    75 
    76    [ ] get doctest coverage to 100% for the number_field directory
     63   [ ] optimization -- make computing an absolute field lazy, and only
     64       do it when we really need it for some computation, e.g.,
     65       mazimal order.
     66 
     67   [ ] this warning: "WARNING: Doing arithmetic in towers of relative
     68fields that depends on canonical coercions is currently VERY SLOW.  It
     69is much better to explicitly coerce all elements into a common field,
     70then do arithmetic with them there (which is quite fast)."
    7771
    7872   [ ] arithmetic/automatic coercions between isomorphic fields, where
    7973       the only difference is the underlying implementation of
     
    8680       [ ] quaternion algebra elements -- deal with that they only work for ntl number field elements
    8781       [ ] matrix_cyclo_dense.pyx
    8882
    89    [ ] write a function that can be included in doctests that
    90        guarantees at least a certain amount of speed.  add this to
    91        library so that nobody can frack my shizzle up.
    92 
    9383   [ ] add proper headers
    9484   [ ] add overview docs to each file
    9585   [ ] overview of everything
     
    10191   [ ] suspicious bound:
    10292     "   D = (Dpoly.numer() * Dpoly.denom()).squarefree_part(bound=10000) "
    10393
    104 OTHER:
     94For LATER:
    10595
    106 [ ] optimize -- creation of the order generated by elements, especially in relative case (use singular?)
    107 [ ] plug in sebastian's code for QQ['x']?
    108 [ ] Organize a similar refactoring for function fields.
    109 [ ] to look into: non-maximal orders and GB's over ZZ???
     96   [ ] write a function that can be included in doctests that
     97       guarantees at least a certain amount of speed.  add this to
     98       library so that nobody can frack my shizzle up.
     99
     100   [ ] benchmark *every single operation* with each type of elements... for sanity
     101   [ ] change number_field_element_quadratic to derive from
     102       number_field_element code (i.e., the abstract base), instead of
     103       deriving from number_field_element_ntl.
     104   [ ] fix all INPUT block list formatting
     105   [ ] move data out of elements into implementation objects for ntl and quadratic types
     106   [ ] optimize -- creation of the order generated by elements, especially in relative case (use singular?)
     107   [ ] plug in sebastian's code for QQ['x']?
     108   [ ] Organize a similar refactoring for function fields.
     109   [ ] to look into: non-maximal orders and GB's over ZZ???
    110110