Ticket #9054: trac_9054-all-parts.patch

File trac_9054-all-parts.patch, 122.0 KB (added by mderickx, 6 years ago)

All patches till review.patch combined

  • module_list.py

    # HG changeset patch
    # User Moritz Minzlaff <minzlaff@daad-alumni.de>
    # Date 1301395342 -7200
    # Node ID 9665e53f2dcd038bdf179898e85c91a56fe0c08b
    # Parent  a8c3967226aaa37e387e5b887a0ffa7f543c3734
    Trac 9054: contains parts 1-12, marteen's additions and final doctest fixes
    * * *
    Trac 9054: polynomial must be defined over the base field
    * * *
    Trac 9054: treat zero correctly
    * * *
    Trac 9054: correct codomain of morphisms
    * * *
    Trac 9054: fixes doctests
    * * *
    imported patch trac_9054_review.patch
    
    diff --git a/module_list.py b/module_list.py
    a b  
    13541354
    13551355        ################################
    13561356        ##
     1357        ## sage.rings.function_field
     1358        ##
     1359        ################################
     1360
     1361    Extension('sage.rings.function_field.function_field_element',
     1362              sources = ['sage/rings/function_field/function_field_element.pyx']),
     1363
     1364        ################################
     1365        ##
    13571366        ## sage.rings.number_field
    13581367        ##
    13591368        ################################
  • sage/categories/all.py

    diff --git a/sage/categories/all.py b/sage/categories/all.py
    a b  
    4141
    4242# fields
    4343from number_fields import NumberFields
     44from function_fields import FunctionFields
    4445
    4546# modules
    4647from left_modules import LeftModules
  • new file sage/categories/function_fields.py

    diff --git a/sage/categories/function_fields.py b/sage/categories/function_fields.py
    new file mode 100644
    - +  
     1r"""
     2FunctionFields
     3"""
     4#*****************************************************************************
     5#  Copyright (C) 2005      David Kohel <kohel@maths.usyd.edu>
     6#                          William Stein <wstein@math.ucsd.edu>
     7#                2008      Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
     8#                2008-2009 Nicolas M. Thiery <nthiery at users.sf.net>
     9#
     10#  Distributed under the terms of the GNU General Public License (GPL)
     11#                  http://www.gnu.org/licenses/
     12#******************************************************************************
     13
     14from sage.categories.category import Category
     15from sage.misc.cachefunc import cached_method
     16from sage.categories.basic import Fields
     17
     18class FunctionFields(Category):
     19    r"""
     20    The category of function fields.
     21
     22    EXAMPLES:
     23
     24    We create the category of function fields::
     25
     26        sage: C = FunctionFields()
     27        sage: C
     28        Category of function fields
     29
     30    TESTS::
     31
     32        sage: TestSuite(FunctionFields()).run()
     33
     34    """
     35
     36    @cached_method
     37    def super_categories(self):
     38        """
     39        Returns the Category of which this is a direct sub-Category
     40        For a list off all super caategories see all_super_categories
     41
     42        EXAMPLES::
     43
     44            sage: FunctionFields().super_categories()
     45            [Category of fields]
     46
     47        """
     48        return[Fields()]
     49
     50
     51    def _call_(self, x):
     52        r"""
     53        Constructs an object in this category from the data in ``x``,
     54        or throws a TypeError.
     55
     56        EXAMPLES::
     57
     58            sage: C = FunctionFields()
     59            sage: K.<x>=FunctionField(QQ)
     60            sage: C(K)
     61            Rational function field in x over Rational Field
     62            sage: Ky.<y> = K[]
     63            sage: L = K.extension(y^2-x)
     64            sage: C(L)
     65            Function field in y defined by y^2 - x
     66            sage: C(L.equation_order())
     67            Function field in y defined by y^2 - x
     68           
     69
     70        """
     71        try:
     72            return x.function_field()
     73        except AttributeError:
     74            raise  TypeError, "unable to canonically associate a function field to %s"%x
     75
     76
     77    class ParentMethods:
     78        pass
     79
     80    class ElementMethods:
     81        pass
  • sage/matrix/matrix2.pyx

    diff --git a/sage/matrix/matrix2.pyx b/sage/matrix/matrix2.pyx
    a b  
    54665466            sage: C.echelon_form()
    54675467            Traceback (most recent call last):
    54685468            ...
    5469             NotImplementedError: Echelon form not implemented over 'Univariate Polynomial Ring in x over Integer Ring'.
     5469            NotImplementedError: Ideal Ideal (2, x + 1) of Univariate Polynomial Ring in x over Integer Ring not principal
     5470            Echelon form not implemented over 'Univariate Polynomial Ring in x over Integer Ring'.
    54705471            sage: C = matrix(3,[2,x,x^2,x+1,3-x,-1,3,2,1/2])
    54715472            sage: C.echelon_form()
    54725473            [                               2                                x                              x^2]
     
    55605561        else:
    55615562            try:
    55625563                a, d, p = self._echelon_form_PID()
    5563             except TypeError:
    5564                 raise NotImplementedError, "echelon form over %s not yet implemented"%self.base_ring()
     5564            except TypeError, msg:
     5565                raise NotImplementedError, "%s\nechelon form over %s not yet implemented"%(msg, self.base_ring())
    55655566
    55665567            for c from 0 <= c < self.ncols():
    55675568               for r from 0 <= r < self.nrows():
     
    57135714                    kwds['algorithm'] = algorithm
    57145715                return self._echelonize_ring(**kwds)
    57155716        except ArithmeticError, msg:
    5716             raise NotImplementedError, "Echelon form not implemented over '%s'."%self.base_ring()
     5717            raise NotImplementedError, "%s\nEchelon form not implemented over '%s'."%(msg,self.base_ring())
    57175718
    57185719    def echelon_form(self, algorithm="default", cutoff=0, **kwds):
    57195720        """
     
    1009610097        dp, up, vp = _smith_diag(d)
    1009710098        return dp,up*u,v*vp
    1009810099
     10100    def hermite_form(self, include_zero_rows=True, transformation=False):
     10101        """
     10102        Return the Hermite form of self, if it is defined.
     10103
     10104        INPUT:
     10105
     10106            - ``include_zero_rows`` -- bool (default: True); if False
     10107              the zero rows in the output matrix are deleted.
     10108
     10109            - ``transformation`` -- bool (default: False) a matrix U such that U*self == H.
     10110
     10111        OUTPUT:
     10112
     10113            - matrix H
     10114            - (optional) transformation matrix U such that U*self == H, possibly with zero
     10115              rows deleted...
     10116       
     10117
     10118        EXAMPLES::
     10119
     10120            sage: M = FunctionField(GF(7),'x').maximal_order()
     10121            sage: K.<x> = FunctionField(GF(7)); M = K.maximal_order()
     10122            sage: A = matrix(M, 2, 3, [x, 1, 2*x, x, 1+x, 2])
     10123            sage: A.hermite_form()
     10124            [      x       1     2*x]
     10125            [      0       x 5*x + 2]
     10126            sage: A.hermite_form(transformation=True)
     10127            (
     10128            [      x       1     2*x]  [1 0]
     10129            [      0       x 5*x + 2], [6 1]
     10130            )
     10131            sage: A = matrix(M, 2, 3, [x, 1, 2*x, 2*x, 2, 4*x])
     10132            sage: A.hermite_form(transformation=True, include_zero_rows=False)
     10133            ([  x   1 2*x], [1 0])
     10134            sage: H, U = A.hermite_form(transformation=True, include_zero_rows=True); H, U
     10135            (
     10136            [  x   1 2*x]  [1 0]
     10137            [  0   0   0], [5 1]
     10138            )
     10139            sage: U*A == H
     10140            True
     10141            sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False)
     10142            sage: U*A
     10143            [  x   1 2*x]
     10144            sage: U*A == H
     10145            True
     10146        """
     10147        left, H, pivots = self._echelon_form_PID()
     10148        if not include_zero_rows:
     10149            i = H.nrows() - 1
     10150            while H.row(i) == 0:
     10151                i -= 1
     10152            H = H[:i+1]
     10153            if transformation:
     10154                left = left[:i+1]
     10155        if transformation:
     10156            return H, left
     10157        else:
     10158            return H
     10159
    1009910160    def _echelon_form_PID(self):
    1010010161        r"""
    1010110162        Return a triple (left, a, pivots) where left*self == a and a is row
     
    1140911470        if a[k,0] not in I:
    1141011471            try:
    1141111472                v = R.ideal(a[0,0], a[k,0]).gens_reduced()
    11412             except:
    11413                 raise ArithmeticError, "Can't create ideal on %s and %s" % (a[0,0], a[k,0])
     11473            except Exception, msg:
     11474                raise ArithmeticError, "%s\nCan't create ideal on %s and %s" % (msg, a[0,0], a[k,0])
    1141411475            if len(v) > 1:
    1141511476                raise ArithmeticError, "Ideal %s not principal" %  R.ideal(a[0,0], a[k,0])
    1141611477            B = v[0]
  • sage/misc/sage_unittest.py

    diff --git a/sage/misc/sage_unittest.py b/sage/misc/sage_unittest.py
    a b  
    1313import unittest
    1414import sys
    1515import traceback
     16import misc
    1617
    1718class TestSuite(object):
    1819    """
     
    254255        In conjonction with ``%pdb on``, this allows for the debbuger
    255256        to jump directly to the first failure location.
    256257        """
     258        time = options.get('cputime')
    257259        if type(skip) == str:
    258260            skip = [skip]
    259261        else:
     
    270272                # TODO: improve pretty printing
    271273                # could use the doc string of the test method?
    272274                tester.info(tester._prefix+"running .%s() . . ."%method_name, newline = False)
     275                if time:
     276                    start_time = misc.cputime()
    273277                test_method = getattr(self._instance, method_name)
    274278                try:
    275279                    test_method(tester = tester)
    276                     tester.info(" pass")
     280                    tester.info(" pass", newline = not time)
     281                    if time:
     282                        tester.info(", cputime: %f"%misc.cputime(start_time))
    277283                except catch_exception as e:
    278284                    failed.append(method_name)
    279285                    if isinstance(e, TestSuiteFailure):
  • sage/modules/free_module.py

    diff --git a/sage/modules/free_module.py b/sage/modules/free_module.py
    a b  
    10111011            for a in c:
    10121012                try:
    10131013                    b = R(a)
    1014                 except (TypeError):
     1014                except (TypeError, ValueError):
    10151015                    return False
    10161016                except NotImplementedError:
    10171017                    from sage.rings.all import ZZ
  • sage/rings/all.py

    diff --git a/sage/rings/all.py b/sage/rings/all.py
    a b  
    6767# Number field
    6868from number_field.all import *
    6969
     70# Function field
     71from function_field.all import *
     72
    7073# p-adic field
    7174from padics.all import *
    7275from padics.padic_printing import _printer_defaults as padic_printing
  • new file sage/rings/function_field/__init__.py

    diff --git a/sage/rings/function_field/__init__.py b/sage/rings/function_field/__init__.py
    new file mode 100644
    - +  
     1# Function fields
  • new file sage/rings/function_field/all.py

    diff --git a/sage/rings/function_field/all.py b/sage/rings/function_field/all.py
    new file mode 100644
    - +  
     1from constructor import FunctionField
     2
     3
  • new file sage/rings/function_field/constructor.py

    diff --git a/sage/rings/function_field/constructor.py b/sage/rings/function_field/constructor.py
    new file mode 100644
    - +  
     1import function_field
     2from sage.misc.cachefunc import cached_function
     3from sage.misc.decorators import sage_wraps
     4
     5
     6def FunctionField(X,names):
     7    """
     8    Return the function field in one variable with constant field X. The function
     9    field returned is unique in the sence that if you call this function twice
     10    with the same base field and name then you get the same python object back.
     11
     12    INPUT:
     13
     14        - `X` -- a field; return the function field in one variable over X.
     15
     16        - ``names`` -- name of variable as a string or a tuple containg a string
     17   
     18    EXAMPLES::
     19
     20        sage: FunctionField(QQ,'alpha')
     21        Rational function field in alpha over Rational Field
     22        sage: K.<alpha> = FunctionField(GF(7)); K
     23        Rational function field in alpha over Finite Field of size 7
     24    """
     25    if not isinstance(names,tuple):
     26        names = (names,)
     27    return _FunctionField(X,names)
     28
     29
     30@cached_function
     31def _FunctionField(X, names):
     32    """
     33    Does exactly the same as FunctionField, but with the disadvantage that it
     34    cannot be used for Pickling since it is decorated.
     35
     36    INPUT:
     37
     38        - `X` -- a field; return the function field in one variable over X.
     39
     40        - ``names`` -- name of variable as a string
     41   
     42    EXAMPLES::
     43
     44        sage: FunctionField(QQ,'alpha')
     45        Rational function field in alpha over Rational Field
     46        sage: K.<alpha> = FunctionField(GF(7)); K
     47        Rational function field in alpha over Finite Field of size 7
     48
     49    """
     50    return function_field.RationalFunctionField(X, names=names)
     51
     52
     53def FunctionField_polymod_Constructor(polynomial, names):
     54    """
     55    Constructs a FunctionField_polymod instance. This function takes care
     56    that it's unique.
     57
     58    EXAMPLES::
     59
     60        sage: K.<x> = FunctionField(QQ)
     61        sage: R.<y>=K[]
     62        sage: y2 = y*1
     63        sage: y2 is y
     64        False
     65        sage: L.<w>=K.extension(x-y^2) #indirect doctest
     66        sage: M.<w>=K.extension(x-y2^2) #indirect doctest
     67        sage: L is M
     68        True
     69   
     70    """
     71    from sage.rings.polynomial.all import is_Polynomial
     72    if polynomial.parent().ngens()>1 or not is_Polynomial(polynomial):
     73        raise TypeError, "polynomial must be univariate a polynomial"
     74    if names is None:
     75        names = (polynomial.variable_name(), )
     76    if not isinstance(names,tuple):
     77        names = (names,)
     78    return _FunctionField_polymod_Constructor(polynomial, names)
     79
     80@cached_function
     81def _FunctionField_polymod_Constructor(polynomial, names):
     82    """
     83    Does exactly the same as FunctionField_polymod, but with the disadvantage that it
     84    cannot be used for Pickling since it is decorated.
     85
     86   
     87    EXAMPLES::
     88
     89        sage: K.<x> = FunctionField(QQ)
     90        sage: R.<y>=K[]
     91        sage: y2 = y*1
     92        sage: y2 is y
     93        False
     94        sage: L.<w>=K.extension(x-y^2) #indirect doctest
     95        sage: M.<w>=K.extension(x-y2^2) #indirect doctest
     96        sage: L is M
     97        True
     98   
     99
     100    """
     101    return function_field.FunctionField_polymod(polynomial, names)
     102   
  • new file sage/rings/function_field/function_field.py

    diff --git a/sage/rings/function_field/function_field.py b/sage/rings/function_field/function_field.py
    new file mode 100644
    - +  
     1r"""
     2Function fields
     3
     4EXAMPLES::
     5
     6We create an extension of a rational function fields, and do some
     7simple arithmetic in it::
     8
     9    sage: K.<x> = FunctionField(GF(5^2,'a')); K
     10    Rational function field in x over Finite Field in a of size 5^2
     11    sage: R.<y> = K[]
     12    sage: L.<y> = K.extension(y^3 - (x^3 + 2*x*y + 1/x)); L
     13    Function field in y defined by y^3 + 3*x*y + (4*x^4 + 4)/x
     14    sage: y^2
     15    y^2
     16    sage: y^3
     17    2*x*y + (x^4 + 1)/x
     18    sage: a = 1/y; a
     19    (4*x/(4*x^4 + 4))*y^2 + 2*x^2/(4*x^4 + 4)
     20    sage: a * y
     21    1
     22
     23We next make an extension of the above function field, illustrating
     24that arithmetic with a tower of 3 fields is fully supported::
     25
     26    sage: S.<t> = L[]
     27    sage: M.<t> = L.extension(t^2 - x*y)
     28    sage: M
     29    Function field in t defined by t^2 + 4*x*y
     30    sage: t^2
     31    x*y
     32    sage: 1/t
     33    ((1/(x^4 + 1))*y^2 + 2*x/(4*x^4 + 4))*t
     34    sage: M.base_field()
     35    Function field in y defined by y^3 + 3*x*y + (4*x^4 + 4)/x
     36    sage: M.base_field().base_field()
     37    Rational function field in x over Finite Field in a of size 5^2
     38
     39TESTS::
     40
     41    sage: TestSuite(K).run() #long time
     42    sage: TestSuite(L).run() #long time
     43    sage: TestSuite(M).run() #long time
     44   
     45The following tow test suites do not pass '_test_elements' yet since
     46R.an_element() has a _test_category method wich it should not have.
     47It is not the fault of the function field code so this will
     48be fixed in another ticket.
     49    sage: TestSuite(R).run(skip = '_test_elements') #long time
     50    sage: TestSuite(S).run(skip = '_test_elements') #long time
     51
     52   
     53"""
     54
     55from sage.structure.category_object import CategoryObject
     56from sage.rings.ring import Field
     57from sage.rings.integer_ring import ZZ
     58from sage.structure.parent_gens import ParentWithGens
     59from sage.structure.parent import Parent
     60import function_field_element
     61import constructor
     62from sage.categories.function_fields import FunctionFields
     63CAT = FunctionFields()
     64
     65import maps
     66
     67def is_FunctionField(x):
     68    """
     69    Return True if x is of function field type.
     70
     71    EXAMPLES::
     72   
     73        sage: from sage.rings.function_field.function_field import is_FunctionField
     74        sage: is_FunctionField(QQ)
     75        False
     76        sage: is_FunctionField(FunctionField(QQ,'t'))
     77        True
     78    """
     79    return isinstance(x, FunctionField)
     80
     81
     82class FunctionField(Field):
     83    """
     84    The abstract base class for all function fields.
     85   
     86    EXAMPLES::
     87   
     88        sage: K.<x> = FunctionField(QQ)
     89        sage: isinstance(K, sage.rings.function_field.function_field.FunctionField)
     90        True
     91    """
     92    def some_elements(self):
     93         #the number of ellements could be made bigger late rbut right now the
     94         #TestSuite(F).run() take to long with more elements.
     95         return (self.random_element() for i in xrange(3))
     96
     97    def characteristic(self):
     98        """
     99        Return the characteristic of this function field.
     100
     101        EXAMPLES::
     102
     103            sage: R.<t> = FunctionField(QQ)
     104            sage: R.characteristic()
     105            0
     106            sage: R.<t> = FunctionField(GF(7))
     107            sage: R.characteristic()
     108            7       
     109        """
     110        return self.constant_field().characteristic()
     111   
     112    def is_finite(self):
     113        """
     114        Return whether this function field is finite, which it is not.
     115
     116        EXAMPLES::
     117
     118            sage: R.<t> = FunctionField(QQ)
     119            sage: R.is_finite()
     120            False
     121            sage: R.<t> = FunctionField(GF(7))
     122            sage: R.is_finite()
     123            False
     124        """
     125        return False
     126   
     127    def extension(self, f, names=None):
     128        """
     129        Create an extension L = K[y]/(f(y)) of a function field,
     130        defined by a univariate polynomial in one variable over this
     131        function field K.
     132
     133        INPUT:
     134       
     135            - `f` -- a univariate polynomial over self
     136            - ``names`` -- None or string or length-1 tuple
     137
     138        OUTPUT:
     139
     140            - a function field
     141       
     142        EXAMPLES::
     143       
     144            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     145            sage: K.extension(y^5 - x^3 - 3*x + x*y)
     146            Function field in y defined by y^5 + x*y - x^3 - 3*x
     147
     148        A nonintegral defining polynomial::
     149
     150            sage: K.<t> = FunctionField(QQ); R.<y> = K[]
     151            sage: K.extension(y^3 + (1/t)*y + t^3/(t+1))
     152            Function field in y defined by y^3 + 1/t*y + t^3/(t + 1)
     153
     154        The defining polynomial need not be monic or integral::
     155
     156            sage: K.extension(t*y^3 + (1/t)*y + t^3/(t+1))
     157            Function field in y defined by t*y^3 + 1/t*y + t^3/(t + 1)
     158        """
     159        return constructor.FunctionField_polymod_Constructor(f, names)
     160
     161    def order_with_basis(self, basis, check=True):
     162        """
     163        Return the order with given basis over the maximal order of
     164        the base field.
     165
     166        INPUT:
     167
     168           - ``basis`` -- a list of elements of self
     169           - ``check`` -- bool (default: True); if True, check that
     170             the basis is really linearly independent and that the
     171             module it spans is closed under multiplication, and
     172             contains the identity element.
     173
     174        OUTPUT:
     175
     176            - an order in this function field
     177
     178        EXAMPLES::
     179
     180            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^3 + x^3 + 4*x + 1)
     181            sage: O = L.order_with_basis([1, Y, Y^2]); O
     182            Order in Function field in Y defined by y^3 + x^3 + 4*x + 1
     183            sage: O.basis()
     184            (1, Y, Y^2)
     185
     186        Note that 1 does not need to be an element of the basis, as long it is in the module spanned by it::
     187
     188            sage: O = L.order_with_basis([1+Y, Y, Y^2]); O
     189            Order in Function field in Y defined by y^3 + x^3 + 4*x + 1
     190            sage: O.basis()
     191            (Y + 1, Y, Y^2)
     192       
     193
     194        The following error is raised when the module spanned by the basis is not closed under multiplication::
     195
     196            sage: O = L.order_with_basis([1, x^2 + x*Y, (2/3)*Y^2]); O
     197            Traceback (most recent call last):
     198            ...
     199            ValueError: The module generated by basis [1, x*Y + x^2, 2/3*Y^2] must be closed under multiplication
     200           
     201        and this happens when the identity is not in the module spanned by the basis::
     202
     203            sage: O = L.order_with_basis([x, x^2 + x*Y, (2/3)*Y^2])
     204            Traceback (most recent call last):
     205            ...
     206            ValueError: The identity element must be in the module spanned by basis [x, x*Y + x^2, 2/3*Y^2]
     207           
     208
     209        """
     210        from function_field_order import FunctionFieldOrder_basis
     211        return FunctionFieldOrder_basis([self(a) for a in basis], check=check)
     212
     213    def order(self, x, check=True):
     214        """
     215        Return the order in this function field generated over the
     216        maximal order by x or the elements of x if x is a list.
     217
     218        INPUT:
     219       
     220           - ``x`` -- element of self, or a list of elements of self
     221           - ``check`` -- bool (default: True); if True, check that
     222             x really generates an order
     223
     224        EXAMPLES::
     225
     226            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^3 + x^3 + 4*x + 1)
     227            sage: O = L.order(Y); O
     228            Order in Function field in Y defined by y^3 + x^3 + 4*x + 1
     229            sage: O.basis()
     230            (1, Y, Y^2)
     231
     232            sage: Z = K.order(x); Z
     233            Order in Rational function field in x over Rational Field
     234            sage: Z.basis()
     235            (1,)
     236
     237        Orders with multiple generators, not yet supported::
     238
     239            sage: Z = K.order([x,x^2]); Z
     240            Traceback (most recent call last):
     241            ...
     242            NotImplementedError
     243        """
     244        if not isinstance(x, (list, tuple)):
     245            x = [x]
     246        if len(x) == 1:
     247            g = x[0]
     248            basis = [self(1)]
     249            for i in range(self.degree()-1):
     250                basis.append(basis[-1]*g)
     251        else:
     252            raise NotImplementedError
     253        return self.order_with_basis(basis, check=check)
     254
     255    def _coerce_map_from_(self, R):
     256        """
     257        Return True if there is a coerce map from R to self.
     258
     259        EXAMPLES::
     260
     261            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^3 + x^3 + 4*x + 1)
     262            sage: L.equation_order()
     263            Order in Function field in Y defined by y^3 + x^3 + 4*x + 1
     264            sage: L._coerce_map_from_(L.equation_order())
     265            True
     266            sage: L._coerce_map_from_(GF(7))
     267            False
     268        """
     269        from function_field_order import FunctionFieldOrder
     270        if isinstance(R, FunctionFieldOrder) and R.fraction_field() == self:
     271            return True
     272        return False
     273
     274    def hom(self, im_gens, base_morphism=None):
     275        """
     276        Create a homomorphism from self to another function field.
     277       
     278        INPUT:
     279
     280           - ``im_gens`` -- a list of images of the generators of self
     281             and of successive base rings.
     282           
     283           - ``base_morphism`` -- (default: None) a homomorphism of
     284             the base ring, after the im_gens are used.  Thus if
     285             im_gens has length 2, then base_morphism should be a morphism
     286             from self.base_ring().base_ring().
     287
     288        EXAMPLES::
     289       
     290        We create a rational function field, and a quadratic extension of it::
     291       
     292            sage: R.<x> = FunctionField(QQ); S.<y> = R[]
     293            sage: L.<y> = R.extension(y^2 - x^3 - 1)
     294
     295        We make the field automorphism that sends y to -y::
     296       
     297            sage: f = L.hom(-y); f
     298            Morphism of function fields defined by y |--> -y
     299
     300        Evaluation works::
     301       
     302            sage: f(y*x - 1/x)
     303            -x*y - 1/x
     304
     305        We try to define an invalid morphism::
     306       
     307            sage: f = L.hom(y+1); f
     308            Traceback (most recent call last):
     309            ...
     310            ValueError: invalid morphism
     311
     312        We make a morphism of the base rational function field::
     313       
     314            sage: phi = R.hom(x+1); phi
     315            Morphism of function fields defined by x |--> x + 1
     316            sage: phi(x^3 - 3)
     317            x^3 + 3*x^2 + 3*x - 2
     318            sage: (x+1)^3-3
     319            x^3 + 3*x^2 + 3*x - 2
     320
     321        We make a morphism by specifying where the generators and the
     322        base generators go::
     323       
     324            sage: L.hom([-y, x])
     325            Morphism of function fields defined by y |--> -y,  x |--> x
     326
     327        The usage of the keyword base_morphism is not implemented yet::
     328
     329            sage: L.hom([-y, x-1], base_morphism=phi)
     330            Traceback (most recent call last):
     331            ...
     332            NotImplementedError: Function field homorphisms with optional argument base_morphism are not implemented yet. Please specify the images of the generators of the base fields manually.
     333           
     334               
     335        We make another extension of a rational function field::
     336       
     337            sage: R2.<t> = FunctionField(QQ); S2.<w> = R2[]
     338            sage: L2.<w> = R2.extension((4*w)^2 - (t+1)^3 - 1)
     339
     340        We define a morphism, by giving the images of generators::
     341       
     342            sage: f = L.hom([4*w, t+1]); f
     343            Morphism of function fields defined by y |--> 4*w,  x |--> t + 1
     344
     345        Evaluation works, as expected::
     346       
     347            sage: f(y+x)
     348            4*w + t + 1
     349            sage: f(x*y + x/(x^2+1))
     350            (4*t + 4)*w + (t + 1)/(t^2 + 2*t + 2)
     351
     352        We make another extension of a rational function field::
     353
     354            sage: R3.<yy> = FunctionField(QQ); S3.<xx> = R3[]
     355            sage: L3.<xx> = R3.extension(yy^2 - xx^3 - 1)
     356
     357        This is the function field L with the generators exchanged. We define a morphism to L::
     358
     359            sage: g = L3.hom([x,y]); g
     360            Morphism of function fields defined by xx |--> x, yy |--> y
     361
     362        """
     363        if base_morphism is not None:
     364            raise NotImplementedError, "Function field homorphisms with optional argument base_morphism are not implemented yet. Please specify the images of the generators of the base fields manually." 
     365       
     366        if not isinstance(im_gens, (list,tuple)):
     367            im_gens = [im_gens]
     368        if len(im_gens) == 0:
     369            raise ValueError, "no images specified"
     370   
     371        if len(im_gens) > 1:
     372            base_morphism = self.base_field().hom(im_gens[1:], base_morphism)
     373
     374        # the codomain of this morphism is the field containing all the im_gens
     375        codomain = im_gens[0].parent();
     376        if base_morphism is not None:
     377            if base_morphism.codomain().has_coerce_map_from(codomain):
     378                codomain = base_morphism.codomain();
     379
     380        return maps.FunctionFieldMorphism(self.Hom(codomain), im_gens[0], base_morphism)
     381
     382class FunctionField_polymod(FunctionField):
     383    """
     384    A function field defined by a univariate polynomial, as an
     385    extension of the base field.
     386   
     387    EXAMPLES::
     388
     389    We make a function field defined by a degree 5 polynomial over the
     390    rational function field over the rational numbers::
     391   
     392        sage: K.<x> = FunctionField(QQ)
     393        sage: R.<y> = K[]
     394        sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L
     395        Function field in w defined by y^5 - 2*x*y + (-x^4 - 1)/x
     396
     397    We next make a function field over the above nontrivial function
     398    field L::
     399
     400        sage: S.<T> = L[]
     401        sage: M.<alpha> = L.extension(T^2 + w*T + y); M
     402        Function field in alpha defined by T^2 + w*T + w
     403        sage: 1/alpha
     404        ((x/(-x^4 - 1))*w^4 - 2*x^2/(-x^4 - 1))*alpha - 1
     405        sage: alpha * (1/alpha)
     406        1
     407
     408    We drill down the tower of function fields::
     409   
     410        sage: M.base_field()
     411        Function field in w defined by y^5 - 2*x*y + (-x^4 - 1)/x
     412        sage: M.base_field().base_field()
     413        Rational function field in x over Rational Field
     414        sage: M.base_field().base_field().constant_field()
     415        Rational Field
     416        sage: M.constant_base_field()
     417        Rational Field
     418
     419    .. WARNING::
     420
     421        It is not checked if the polynomial used to define this function field is irriducible
     422        Hence it is not guaranteed that this object really is a field!
     423        This is illustrated below.
     424
     425    ::
     426
     427        sage: K.<x>=FunctionField(QQ)
     428        sage: R.<y> = K[]
     429        sage: L.<w>=K.extension(x^2-y^2)
     430        sage: (w-x)*(w+x)
     431        0
     432        sage: 1/(w-x)
     433        1
     434        sage: w-x==0; w+x==0
     435        False
     436        False
     437       
     438    """
     439    def __init__(self, polynomial, names,
     440            element_class = function_field_element.FunctionFieldElement_polymod,
     441            category=CAT):
     442        """
     443        Create a function field defined as an extension of another
     444        function field by adjoining a root of a univariate polynomial.
     445
     446        INPUT:
     447
     448            - ``polynomial`` -- a univariate polynomial over a function field
     449            - ``names`` -- variable names (as a tuple of length 1 or string)
     450            - ``category`` -- a category (defaults to category of function fields)
     451       
     452        EXAMPLES::
     453
     454        We create an extension of function fields::
     455       
     456            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     457            sage: L = K.extension(y^5 - x^3 - 3*x + x*y); L
     458            Function field in y defined by y^5 + x*y - x^3 - 3*x
     459
     460        Note the type::
     461       
     462            sage: type(L)
     463            <class 'sage.rings.function_field.function_field.FunctionField_polymod_with_category'>
     464
     465        We can set the variable name, which doesn't have to be y::
     466       
     467            sage: L.<w> = K.extension(y^5 - x^3 - 3*x + x*y); L
     468            Function field in w defined by y^5 + x*y - x^3 - 3*x
     469
     470        """
     471        from sage.rings.polynomial.all import is_Polynomial
     472        if polynomial.parent().ngens()>1 or not is_Polynomial(polynomial):
     473            raise TypeError, "polynomial must be univariate a polynomial"
     474        if names is None:
     475            names = (polynomial.variable_name(), )
     476        if polynomial.degree() <= 0:
     477            raise ValueError, "polynomial must have positive degree"
     478        base_field = polynomial.base_ring()
     479        if not isinstance(base_field, FunctionField):
     480            raise TypeError, "polynomial must be over a FunctionField"
     481        self._element_class = element_class
     482        self._element_init_pass_parent = False
     483        self._base_field = base_field
     484        self._polynomial = polynomial
     485       
     486        Field.__init__(self, base_field,
     487                                names=names, category = category)
     488
     489        self._hash = hash(polynomial)
     490        self._ring = self._polynomial.parent()
     491        self._populate_coercion_lists_(coerce_list=[base_field, self._ring])
     492        self._gen = self(self._ring.gen())
     493
     494    def __reduce__(self):
     495        return  constructor.FunctionField_polymod_Constructor, (self._polynomial, self._names)
     496
     497
     498
     499    def __hash__(self):
     500        """
     501        Return hash of this function field.
     502       
     503        EXAMPLES::
     504
     505            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     506            sage: L = K.extension(y^5 - x^3 - 3*x + x*y); hash(L)
     507            3183366741743088279             # 64-bit
     508            2003022487                      # 32-bit
     509
     510        """
     511        return self._hash
     512
     513    def monic_integral_model(self, names):
     514        """
     515        Return a function field isomorphic to self, but with defining
     516        polynomial that is monic and integral over the base field.
     517
     518        INPUT::
     519
     520            - ``names`` -- name of the generator of the new field this function constructs
     521
     522        EXAMPLES::
     523
     524            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     525            sage: L.<alpha> = K.extension(x^2*y^5 - 1/x); L
     526            Function field in alpha defined by x^2*y^5 - 1/x
     527            sage: A, from_A, to_A = L.monic_integral_model('beta')
     528            sage: A
     529            Function field in beta defined by y^5 - x^12
     530            sage: from_A
     531            Morphism of function fields defined by beta |--> x^3*alpha
     532            sage: to_A
     533            Morphism of function fields defined by alpha |--> 1/x^3*beta
     534            sage: to_A(alpha)
     535            1/x^3*beta
     536            sage: from_A(to_A(alpha))
     537            alpha
     538            sage: from_A(to_A(1/alpha))
     539            x^3*alpha^4
     540            sage: from_A(to_A(1/alpha)) == 1/alpha
     541            True           
     542        """
     543        g, d = self._make_monic_integral(self.polynomial())
     544        R = self.base_field()
     545        K = R.extension(g, names=names)
     546        to_K = self.hom(K.gen() / d)
     547        from_K = K.hom(self.gen() * d)
     548        return K, from_K, to_K
     549
     550    def _make_monic_integral(self, f):
     551        r"""
     552        Let alpha be a root of f.  This function returns a monic
     553        integral polynomial g and an element d of the base field such
     554        that g(alpha*d) = 0.
     555       
     556        EXAMPLES::
     557       
     558            sage: K.<x> = FunctionField(QQ); R.<y> = K[];
     559            sage: L.<alpha> = K.extension(x^2*y^5 - 1/x)
     560            sage: g, d = L._make_monic_integral(L.polynomial()); g,d
     561            (y^5 - x^12, x^3)
     562            sage: (alpha*d).is_integral()
     563            True
     564            sage: g.is_monic()
     565            True
     566            sage: g(alpha*d)
     567            0
     568       
     569        """
     570        R = f.base_ring()
     571        if not isinstance(R, RationalFunctionField):
     572            raise NotImplementedError
     573       
     574        # make f monic
     575        n = f.degree()
     576        c = f.leading_coefficient()
     577        if c != 1:
     578            f = f / c
     579
     580        # find lcm of denominators
     581        from sage.rings.arith import lcm
     582        # would be good to replace this by minimal...
     583        d = lcm([b.denominator() for b in f.list() if b])
     584        if d != 1:
     585            x = f.parent().gen()
     586            g = (d**n) * f(x/d)
     587        else:
     588            g = f
     589        return g, d
     590
     591    def constant_field(self):
     592        """
     593        Return the algebraic closure of the constant field of the base
     594        field in this function field.
     595
     596        EXAMPLES::
     597
     598            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     599            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
     600            sage: L.constant_field()
     601            Traceback (most recent call last):
     602            ...
     603            NotImplementedError
     604        """
     605        raise NotImplementedError
     606
     607    def constant_base_field(self):
     608        """
     609        Return the constant field of the base rational function field.
     610                   
     611        EXAMPLES::
     612
     613            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     614            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L
     615            Function field in w defined by y^5 - 2*x*y + (-x^4 - 1)/x
     616            sage: L.constant_base_field()
     617            Rational Field
     618            sage: S.<z> = L[]
     619            sage: M.<z> = L.extension(z^2 - w)
     620            sage: M.constant_base_field()
     621            Rational Field
     622           
     623        """
     624        return self.base_field().constant_base_field()
     625
     626    def degree(self):
     627        """
     628        Return the degree of this function field over its base
     629        function field.
     630       
     631        EXAMPLES::
     632
     633            sage: K.<x> = FunctionField(QQ)
     634            sage: R.<y> = K[]
     635            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L
     636            Function field in w defined by y^5 - 2*x*y + (-x^4 - 1)/x
     637            sage: L.degree()
     638            5       
     639             
     640        """
     641        return self._polynomial.degree()
     642       
     643    def _repr_(self):
     644        """
     645        Return string representation of this function field.
     646       
     647        EXAMPLES::
     648
     649            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     650            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
     651            sage: L._repr_()
     652            'Function field in w defined by y^5 - 2*x*y + (-x^4 - 1)/x'
     653       
     654        """
     655        return "Function field in %s defined by %s"%(self.variable_name(), self._polynomial)
     656
     657    def base_field(self):
     658        """
     659        Return the base field of this function field.  This function
     660        field is presented as L = K[y]/(f(y)), and the base field is
     661        by definition the field K.
     662       
     663        EXAMPLES::
     664            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     665            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
     666            sage: L.base_field()
     667            Rational function field in x over Rational Field
     668       
     669        """
     670        return self._base_field
     671
     672
     673    def random_element(self, *args, **kwds):
     674        """
     675        Create a random element of this function field.  Parameters
     676        are passed onto the random_element method of the base_field.
     677
     678        EXAMPLES::
     679
     680            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     681            sage: L.<w> = K.extension(y^2 - (x^2 + x))
     682            sage: L.random_element() # random
     683            ((x^2 - x + 2/3)/(x^2 + 1/3*x - 1))*w^2 + ((-1/4*x^2 + 1/2*x - 1)/(-5/2*x + 2/3))*w + (-1/2*x^2 - 4)/(-12*x^2 + 1/2*x - 1/95)
     684       
     685        """
     686        return self(self._ring.random_element(degree=self.degree(), *args, **kwds))
     687
     688    def polynomial(self):
     689        """
     690        Return the univariate polynomial that defines this function
     691        field, i.e., the polynomial f(y) so that this function field
     692        is of the form K[y]/(f(y)).
     693       
     694        EXAMPLES::
     695
     696            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     697            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
     698            sage: L.polynomial()
     699            y^5 - 2*x*y + (-x^4 - 1)/x
     700       
     701        """
     702        return self._polynomial
     703
     704    def polynomial_ring(self):
     705        """
     706        Return the polynomial ring used to represents elements of this
     707        function field.  If we view this function field as being presented
     708        as K[y]/(f(y)), then this function returns the ring K[y].
     709       
     710        EXAMPLES::
     711
     712            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     713            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
     714            sage: L.polynomial_ring()
     715            Univariate Polynomial Ring in y over Rational function field in x over Rational Field
     716       
     717        """
     718        return self._ring
     719
     720    def vector_space(self):
     721        """
     722        Return a vector space V and isomorphisms self --> V and V --> self.
     723
     724        This function allows us to identify the elements of self with
     725        elements of a vector space over the base field, which is
     726        useful for representation and arithmetic with orders, ideals,
     727        etc.
     728       
     729        OUTPUT:
     730
     731            -  ``V`` - a vector space over base field
     732            -  ``from_V`` - an isomorphism from V to self
     733            -  ``to_V`` - an isomorphism from self to V
     734
     735        EXAMPLES::
     736
     737        We define a function field::
     738       
     739            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     740            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L
     741            Function field in w defined by y^5 - 2*x*y + (-x^4 - 1)/x
     742
     743        We get the vector spaces, and maps back and forth::
     744       
     745            sage: V, from_V, to_V = L.vector_space()
     746            sage: V
     747            Vector space of dimension 5 over Rational function field in x over Rational Field
     748            sage: from_V
     749            Isomorphism map:
     750              From: Vector space of dimension 5 over Rational function field in x over Rational Field
     751              To:   Function field in w defined by y^5 - 2*x*y + (-x^4 - 1)/x
     752            sage: to_V
     753            Isomorphism map:
     754              From: Function field in w defined by y^5 - 2*x*y + (-x^4 - 1)/x
     755              To:   Vector space of dimension 5 over Rational function field in x over Rational Field
     756
     757        We convert an element of the vector space back to the function field::
     758       
     759            sage: from_V(V.1)
     760            w
     761
     762        We define an interesting element of the function field::
     763       
     764            sage: a = 1/L.0; a
     765            (-x/(-x^4 - 1))*w^4 + 2*x^2/(-x^4 - 1)
     766
     767        We convert it to the vector space, and get a vector over the base field::
     768       
     769            sage: to_V(a)
     770            (2*x^2/(-x^4 - 1), 0, 0, 0, -x/(-x^4 - 1))
     771
     772        We convert to and back, and get the same element::
     773       
     774            sage: from_V(to_V(a)) == a
     775            True
     776
     777        In the other direction::
     778
     779            sage: v = x*V.0 + (1/x)*V.1
     780            sage: to_V(from_V(v)) == v
     781            True
     782
     783
     784        And we show how it works over an extension of an extension field.
     785
     786            sage: R2.<z> = L[]; M.<w> = L.extension(z^2 -y)
     787            sage: M.vector_space()
     788            (Vector space of dimension 2 over Function field in w defined by y^5 - 2*x*y + (-x^4 - 1)/x, Isomorphism map:
     789              From: Vector space of dimension 2 over Function field in w defined by y^5 - 2*x*y + (-x^4 - 1)/x
     790              To:   Function field in w defined by z^2 - w, Isomorphism map:
     791              From: Function field in w defined by z^2 - w
     792              To:   Vector space of dimension 2 over Function field in w defined by y^5 - 2*x*y + (-x^4 - 1)/x)
     793                   
     794        """
     795        try: return self._vector_space
     796        except AttributeError:
     797            V = self.base_field()**self.degree()
     798            from_V = maps.MapVectorSpaceToFunctionField(V, self)
     799            to_V   = maps.MapFunctionFieldToVectorSpace(self, V)
     800            self._vector_space = (V, from_V, to_V)
     801            return self._vector_space
     802       
     803
     804    def maximal_order(self):
     805        """
     806        Return the maximal_order of self.  If we view self as L =
     807        K[y]/(f(y)), then this is the ring of elements of L that are
     808        integral over K.
     809       
     810        EXAMPLES::
     811
     812        This is not yet implemented...::
     813       
     814            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     815            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
     816            sage: L.maximal_order()
     817            Traceback (most recent call last):
     818            ...
     819            NotImplementedError
     820       
     821        """
     822        raise NotImplementedError
     823
     824    def _element_constructor_(self, x):
     825        r"""
     826        Make x into an element of this function field, possibly not canonically.
     827
     828        INPUT:
     829       
     830            - ``x`` - the element
     831         
     832        OUTPUT:
     833       
     834            ``x``, as an element of this function field
     835
     836        TESTS::
     837
     838            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     839            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
     840            sage: L._element_constructor_(L.polynomial_ring().gen())
     841            w
     842        """
     843        if x.parent() is self._ring:
     844            return function_field_element.FunctionFieldElement_polymod(self, x)
     845        if isinstance(x, function_field_element.FunctionFieldElement):
     846            return function_field_element.FunctionFieldElement_polymod(self, self._ring(x.element()))           
     847        return function_field_element.FunctionFieldElement_polymod(self, self._ring(x))
     848   
     849
     850    def gen(self, n=0):
     851        """
     852        Return the n-th generator of this function field.  By default n=0; any other
     853        value of n leads to an error.   The generator is the class of y, if we view
     854        self as being presented as K[y]/(f(y)).
     855       
     856        EXAMPLES::
     857
     858            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     859            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
     860            sage: L.gen()
     861            w
     862            sage: L.gen(1)
     863            Traceback (most recent call last):
     864            ...
     865            IndexError: Only one generator.
     866
     867        """
     868        if n != 0: raise IndexError, "Only one generator."
     869        return self._gen
     870
     871    def ngens(self):
     872        """
     873        Return the number of generators of this function field over
     874        its base field.  This is by definition 1.
     875       
     876        EXAMPLES::
     877       
     878            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     879            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
     880            sage: L.ngens()
     881            1
     882        """
     883        return 1
     884
     885    def equation_order(self):
     886        """
     887        If we view self as being presented as K[y]/(f(y)), then this
     888        function returns the order generated by the class of y.  If f
     889        is not monic, then self._make_monic_integral is called, and instead we
     890        get the order generated by some integral multiple of a root of
     891        alpha.
     892       
     893        EXAMPLES::
     894
     895            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     896            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
     897            sage: L.equation_order()
     898            Order in Function field in w defined by y^5 - 2*x*y + (-x^4 - 1)/x
     899
     900        We try an example, in which the defining polynomial is not
     901        monic and is not integral::
     902
     903            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
     904            sage: L.<alpha> = K.extension(x^2*y^5 - 1/x); L
     905            Function field in alpha defined by x^2*y^5 - 1/x
     906            sage: O = L.equation_order(); O
     907            Order in Function field in alpha defined by x^2*y^5 - 1/x
     908            sage: O.basis()
     909            (1, x^3*alpha, x^6*alpha^2, x^9*alpha^3, x^12*alpha^4)
     910       
     911        """
     912        d = self._make_monic_integral(self.polynomial())[1]
     913        return self.order(d*self.gen(), check=False)
     914   
     915
     916class RationalFunctionField(FunctionField):
     917    """
     918    A rational function field K(t) in one variable, over an arbitrary
     919    base field.
     920   
     921    EXAMPLES::
     922
     923        sage: K.<t> = FunctionField(GF(3)); K
     924        Rational function field in t over Finite Field of size 3
     925        sage: K.gen()
     926        t
     927        sage: 1/t + t^3 + 5
     928        (t^4 + 2*t + 1)/t
     929
     930    There are various ways to get at the underlying fields and rings
     931    associated to a rational function field::
     932
     933        sage: K.<t> = FunctionField(GF(7))
     934        sage: K.base_field()
     935        Rational function field in t over Finite Field of size 7
     936        sage: K.field()
     937        Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7
     938        sage: K.constant_field()
     939        Finite Field of size 7
     940        sage: K.maximal_order()
     941        Maximal order in Rational function field in t over Finite Field of size 7
     942
     943    We define a morphism::
     944
     945        sage: K.<W> = FunctionField(QQ)
     946        sage: L = FunctionField(QQ, 'tbar')         # give var name as second input
     947        sage: K.hom(L.gen())
     948        Morphism of function fields defined by W |--> tbar
     949    """
     950    def __init__(self, constant_field, names,
     951            element_class = function_field_element.FunctionFieldElement_rational,
     952            category=CAT):
     953        """
     954        Create a rational function field in one variable.
     955
     956        INPUT:
     957
     958            - ``constant_field`` -- an arbitrary field
     959            - ``names`` -- a string or tuple of length 1
     960            - ``category`` -- default: FunctionFields()
     961       
     962        EXAMPLES::
     963
     964            sage: K.<t> = FunctionField(CC); K
     965            Rational function field in t over Complex Field with 53 bits of precision
     966            sage: K.category()
     967            Category of function fields
     968            sage: FunctionField(QQ[I], 'alpha')
     969            Rational function field in alpha over Number Field in I with defining polynomial x^2 + 1
     970
     971        Must be over a field::
     972       
     973            sage: FunctionField(ZZ, 't')
     974            Traceback (most recent call last):
     975            ...
     976            TypeError: constant_field must be a field
     977        """
     978        if names is None:
     979            raise ValueError, "variable name must be specified"
     980        elif not isinstance(names, tuple):
     981            names = (names, )
     982        if not constant_field.is_field():
     983            raise TypeError, "constant_field must be a field"
     984        self._element_class = element_class
     985        self._element_init_pass_parent = False
     986        Field.__init__(self, self, names=names, category = category)
     987        R = constant_field[names[0]]
     988        self._hash = hash((constant_field, names))
     989        self._constant_field = constant_field
     990        self._ring = R
     991        self._field = R.fraction_field()
     992        self._populate_coercion_lists_(coerce_list=[self._field])
     993        self._gen = self(R.gen())
     994
     995    def __reduce__(self):
     996        return constructor.FunctionField, (self._constant_field, self._names)
     997   
     998    def __hash__(self):
     999        """
     1000        Return hash of this function field.
     1001
     1002        EXAMPLES::
     1003       
     1004            sage: K.<t> = FunctionField(QQ)
     1005            sage: hash(K)
     1006            502145503910697533              # 64-bit
     1007            -500688323                      # 32-bit
     1008                       
     1009        """
     1010        return self._hash
     1011
     1012    def _repr_(self):
     1013        """
     1014        Return string representation of this function field.
     1015       
     1016        EXAMPLES::
     1017       
     1018            sage: K.<t> = FunctionField(QQ)
     1019            sage: K._repr_()
     1020            'Rational function field in t over Rational Field'
     1021
     1022        """
     1023        return "Rational function field in %s over %s"%(
     1024            self.variable_name(), self._constant_field)
     1025
     1026    def _element_constructor_(self, x):
     1027        r"""
     1028        Coerce x into an element of this function field, possibly not canonically.
     1029
     1030        INPUT:
     1031       
     1032            - ``x`` - the element
     1033         
     1034        OUTPUT:
     1035       
     1036            ``x``, as an element of this function field
     1037
     1038        EXAMPLES::
     1039       
     1040            sage: K.<t> = FunctionField(QQ)
     1041            sage: a = K._element_constructor_(K.maximal_order().gen()); a
     1042            t
     1043            sage: a.parent()
     1044            Rational function field in t over Rational Field
     1045       
     1046        """
     1047        #if isinstance(x, self._element_class):
     1048        #    if x.parent() is self:
     1049        #        return x
     1050        #    else:
     1051        #        return self._element_class(self, x)
     1052        #return self._element_class(self, x, y,
     1053        #        coerce=coerce, reduce = self.is_exact())
     1054        if x.parent() is self._field:
     1055            return function_field_element.FunctionFieldElement_rational(self, x)
     1056        if isinstance(x, function_field_element.FunctionFieldElement):
     1057            return function_field_element.FunctionFieldElement_rational(self, self._field(x.element()))
     1058        if x.parent() is self.polynomial_ring():
     1059            return x[0]
     1060        return function_field_element.FunctionFieldElement_rational(self, self._field(x))
     1061
     1062    # nonoptimized
     1063    def _to_bivariate_polynomial(self, f):
     1064        """
     1065        Convert f from a univariate polynomial over the rational function
     1066        field into a bivariate polynomial and a denominator.
     1067
     1068        INPUT:
     1069
     1070            - f -- a univariate polynomial over self.
     1071
     1072        OUTPUT:
     1073
     1074            - 2-variate polynomial, denominator
     1075
     1076        EXAMPLES::
     1077       
     1078            sage: R.<t> = FunctionField(GF(7))
     1079            sage: S.<X> = R[]
     1080            sage: f = (1/t)*(X^4 - 1/t^2)*(X^3 - t^3)
     1081            sage: R._to_bivariate_polynomial(f)
     1082            (X^7*t^2 - X^4*t^5 - X^3 + t^3, t^3)       
     1083        """
     1084        v = f.list()
     1085        from sage.rings.arith import LCM
     1086        denom = LCM([a.denominator() for a in v])
     1087        S = denom.parent()
     1088        x,t = S.base_ring()['%s,%s'%(f.parent().variable_name(),self.variable_name())].gens()
     1089        phi = S.hom([t])
     1090        return sum([phi((denom * v[i]).numerator()) * x**i for i in range(len(v))]), denom
     1091
     1092    def _factor_univariate_polynomial(self, f, proof=True):
     1093        """
     1094        Factor the univariate polynomial f over self.
     1095
     1096        EXAMPLES::
     1097
     1098        We do a factorization over the function field over the rationals::
     1099
     1100            sage: R.<t> = FunctionField(QQ)
     1101            sage: S.<X> = R[]
     1102            sage: f = (1/t)*(X^4 - 1/t^2)*(X^3 - t^3)
     1103            sage: f.factor()             # indirect doctest
     1104            (1/t) * (X - t) * (X^2 - 1/t) * (X^2 + 1/t) * (X^2 + t*X + t^2)
     1105            sage: f.factor().prod() == f
     1106            True       
     1107
     1108        You must pass in proof=False over finite fields, due to
     1109        Singular's factoring algorithm being incomplete::
     1110
     1111            sage: R.<t> = FunctionField(GF(7))
     1112            sage: S.<X> = R[]
     1113            sage: f = (1/t)*(X^4 - 1/t^2)*(X^3 - t^3)
     1114            sage: f.factor()
     1115            Traceback (most recent call last):
     1116            ...
     1117            NotImplementedError: proof = True factorization not implemented.  Call factor with proof=False.
     1118            sage: f.factor(proof=False)
     1119            (1/t) * (X + 3*t) * (X + 5*t) * (X + 6*t) * (X^2 + 1/t) * (X^2 + 6/t)
     1120            sage: f.factor(proof=False).prod() == f
     1121            True
     1122
     1123        Factoring over a function field over a non-prime finite field::
     1124
     1125            sage: k.<a> = GF(9)
     1126            sage: R.<t> = FunctionField(k)
     1127            sage: S.<X> = R[]
     1128            sage: f = (1/t)*(X^3 - a*t^3)
     1129            sage: f.factor(proof=False)
     1130            (1/t) * (X + (a + 2)*t)^3
     1131            sage: f.factor(proof=False).prod() == f
     1132            True
     1133
     1134        """
     1135        F, d = self._to_bivariate_polynomial(f)
     1136        fac = F.factor(proof=proof)
     1137        x = f.parent().gen()
     1138        t = f.parent().base_ring().gen()
     1139        phi = F.parent().hom([x, t])
     1140        v = [(phi(P),e) for P, e in fac]
     1141        unit = phi(fac.unit())/d
     1142        w = []
     1143        for a, e in v:
     1144            c = a.leading_coefficient()
     1145            a = a/c
     1146            unit *= (c**e)
     1147            w.append((a,e))
     1148        from sage.structure.factorization import Factorization
     1149        return Factorization(w, unit=unit)
     1150
     1151    def polynomial_ring(self, var='x'):
     1152        """
     1153        Return polynomial ring K[var] that could be used to represent
     1154        elements of self, if self were viewed as K[var]/(var).
     1155       
     1156        EXAMPLES::
     1157       
     1158            sage: K.<x> = FunctionField(QQ)
     1159            sage: K.polynomial_ring()
     1160            Univariate Polynomial Ring in x over Rational function field in x over Rational Field
     1161            sage: K.polynomial_ring('T')
     1162            Univariate Polynomial Ring in T over Rational function field in x over Rational Field
     1163       
     1164        """
     1165        if var != 'x': return self[var]
     1166        try: return self._polynomial_ring
     1167        except AttributeError:
     1168            self._polynomial_ring = self[var]
     1169            return self._polynomial_ring
     1170
     1171    def vector_space(self):
     1172        """
     1173        Return a vector space V and isomorphisms self --> V and V --> self.
     1174       
     1175        OUTPUT:
     1176
     1177            -  ``V`` - a vector space over the rational numbers
     1178            -  ``from_V`` - an isomorphism from V to self
     1179            -  ``to_V`` - an isomorphism from self to V
     1180
     1181        EXAMPLES::
     1182
     1183            sage: K.<x> = FunctionField(QQ)
     1184            sage: K.vector_space()
     1185            (Vector space of dimension 1 over Rational function field in x over Rational Field, Isomorphism map:
     1186              From: Vector space of dimension 1 over Rational function field in x over Rational Field
     1187              To:   Rational function field in x over Rational Field, Isomorphism map:
     1188              From: Rational function field in x over Rational Field
     1189              To:   Vector space of dimension 1 over Rational function field in x over Rational Field)
     1190       
     1191        """
     1192        try: return self._vector_space
     1193        except AttributeError:
     1194            V = self.base_field()**1
     1195            from_V = maps.MapVectorSpaceToFunctionField(V, self)
     1196            to_V   = maps.MapFunctionFieldToVectorSpace(self, V)
     1197            self._vector_space = (V, from_V, to_V)
     1198            return self._vector_space
     1199
     1200    def random_element(self, *args, **kwds):
     1201        """
     1202        Create a random element of this rational function field.
     1203        Parameters are passed onto the random_element method of the
     1204        underlying fraction field.
     1205
     1206        EXAMPLES::
     1207
     1208            sage: FunctionField(QQ,'alpha').random_element()
     1209            (-1/2*alpha^2 - 4)/(-12*alpha^2 + 1/2*alpha - 1/95)
     1210       
     1211        """
     1212        return self(self._field.random_element(*args, **kwds))
     1213
     1214    def degree(self):
     1215        """
     1216        Return the degree over the base field of this rational
     1217        function field, which is 1.
     1218       
     1219        EXAMPLES::
     1220       
     1221            sage: K.<t> = FunctionField(QQ)
     1222            sage: K.degree()
     1223            1
     1224       
     1225        """
     1226        return ZZ(1)
     1227   
     1228    def gen(self, n=0):
     1229        """
     1230        Return the n-th generator of this function field.  If n is not
     1231        0, then an IndexError is raised.
     1232
     1233        EXAMPLES::
     1234           
     1235            sage: K.<t> = FunctionField(QQ); K.gen()
     1236            t
     1237            sage: K.gen().parent()
     1238            Rational function field in t over Rational Field
     1239            sage: K.gen(1)
     1240            Traceback (most recent call last):
     1241            ...
     1242            IndexError: Only one generator.
     1243        """
     1244        if n != 0:
     1245            raise IndexError, "Only one generator."
     1246        return self._gen
     1247
     1248    def ngens(self):
     1249        """
     1250        Return the number of generators, which is 1.
     1251       
     1252        EXAMPLES::
     1253
     1254            sage: K.<t> = FunctionField(QQ)
     1255            sage: K.ngens()
     1256            1
     1257       
     1258        """
     1259        return 1
     1260   
     1261    def base_field(self):
     1262        """
     1263        Return the base field of this rational function field, which is just
     1264        this function field itself.
     1265       
     1266        EXAMPLES::
     1267       
     1268            sage: K.<t> = FunctionField(GF(7))
     1269            sage: K.base_field()
     1270            Rational function field in t over Finite Field of size 7
     1271       
     1272        """
     1273        return self
     1274
     1275    def hom(self, im_gens, base_morphism=None):
     1276        """
     1277        Create a homomorphism from self to another function field.
     1278
     1279        INPUT:
     1280
     1281            - ``im_gens`` -- exactly one element of some function field
     1282            - ``base_morphism`` -- ignored
     1283
     1284        OUTPUT:
     1285
     1286            - a map between function fields
     1287
     1288        EXAMPLES::
     1289
     1290        We make a map from a rational function field to itself::
     1291
     1292            sage: R.<x> = FunctionField(GF(7))
     1293            sage: R.hom( (x^4 + 2)/x)
     1294            Morphism of function fields defined by x |--> (x^4 + 2)/x       
     1295       
     1296        We construct a map from a rational function field into a
     1297        non-rational extension field::
     1298       
     1299            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     1300            sage: L.<y> = R.extension(y^3 + 6*x^3 + x)
     1301            sage: f = R.hom(y^2 + y  + 2); f
     1302            Morphism of function fields defined by x |--> y^2 + y + 2
     1303            sage: f(x)
     1304            y^2 + y + 2
     1305            sage: f(x^2)
     1306            5*y^2 + (x^3 + 6*x + 4)*y + 2*x^3 + 5*x + 4       
     1307       
     1308        """
     1309        if isinstance(im_gens, CategoryObject):
     1310            return self.Hom(im_gens).natural_map()
     1311        if not isinstance(im_gens, (list,tuple)):
     1312            im_gens = [im_gens]
     1313        if len(im_gens) != 1:
     1314            raise ValueError, "there must be exactly one generator"
     1315        x = im_gens[0]
     1316        return maps.FunctionFieldMorphism_rational(self.Hom(x.parent()), x)
     1317
     1318    def field(self):
     1319        """
     1320        Return the underlying field, forgetting the function field
     1321        structure.
     1322       
     1323        EXAMPLES::
     1324
     1325            sage: K.<t> = FunctionField(GF(7))
     1326            sage: K.field()
     1327            Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7
     1328       
     1329        """
     1330        return self._field
     1331
     1332    def maximal_order(self):
     1333        """
     1334        Return the maximal order of this function field.  Since this
     1335        is a rational function field it is of the form K(t), and the
     1336        maximal order is by definition K[t].
     1337       
     1338        EXAMPLES::
     1339       
     1340            sage: K.<t> = FunctionField(QQ)
     1341            sage: K.maximal_order()
     1342            Maximal order in Rational function field in t over Rational Field
     1343            sage: K.equation_order()
     1344            Maximal order in Rational function field in t over Rational Field
     1345       
     1346        """
     1347        try: return self._maximal_order
     1348        except AttributeError:
     1349            from function_field_order import FunctionFieldOrder_rational
     1350            self._maximal_order = FunctionFieldOrder_rational(self)
     1351            return self._maximal_order
     1352
     1353    equation_order = maximal_order
     1354
     1355    def constant_base_field(self):
     1356        """
     1357        Return the field that this rational function field is a
     1358        transcendental extension of.
     1359
     1360        EXAMPLES::
     1361
     1362            sage: K.<t> = FunctionField(QQ)
     1363            sage: K.constant_field()
     1364            Rational Field
     1365       
     1366        """
     1367        return self._constant_field
     1368
     1369    constant_field = constant_base_field
     1370
     1371
     1372       
     1373
     1374   
     1375
     1376
  • new file sage/rings/function_field/function_field_element.pyx

    diff --git a/sage/rings/function_field/function_field_element.pyx b/sage/rings/function_field/function_field_element.pyx
    new file mode 100644
    - +  
     1include "../../ext/stdsage.pxi"
     2
     3from sage.structure.element cimport FieldElement, RingElement, ModuleElement, Element
     4
     5def is_FunctionFieldElement(x):
     6    """
     7    Return True if x is any type of function field element.
     8   
     9    EXAMPLES::
     10
     11        sage: t = FunctionField(QQ,'t').gen()
     12        sage: sage.rings.function_field.function_field_element.is_FunctionFieldElement(t)
     13        True
     14        sage: sage.rings.function_field.function_field_element.is_FunctionFieldElement(0)
     15        False
     16    """
     17    return isinstance(x, FunctionFieldElement)
     18
     19def make_FunctionFieldElement(parent, element_class, representing_element):
     20    """
     21    Used for unpickling FunctionFieldElement objects (and subclasses).
     22   
     23    EXAMPLES::
     24   
     25        sage: from sage.rings.function_field.function_field_element import make_FunctionFieldElement
     26        sage: K.<x> = FunctionField(QQ)
     27        sage: make_FunctionFieldElement(K, K._element_class, (x+1)/x)
     28        (x + 1)/x
     29   
     30    """
     31    return element_class(parent, representing_element, reduce=False)
     32
     33cdef class FunctionFieldElement(FieldElement):
     34
     35    cdef readonly object _x
     36    cdef readonly object _matrix
     37   
     38    """
     39    The abstract base class for function field elements.
     40   
     41    EXAMPLES::
     42
     43        sage: t = FunctionField(QQ,'t').gen()
     44        sage: isinstance(t, sage.rings.function_field.function_field_element.FunctionFieldElement)
     45        True
     46    """
     47
     48    def __reduce__(self):
     49        """
     50        EXAMPLES::
     51       
     52            sage: K = FunctionField(QQ,'x')
     53            sage: f = K.random_element()
     54            sage: loads(f.dumps()) == f
     55            True
     56        """
     57        return (make_FunctionFieldElement,
     58                (self._parent, type(self), self._x))
     59
     60
     61    cdef FunctionFieldElement _new_c(self):
     62        cdef FunctionFieldElement x = <FunctionFieldElement>PY_NEW_SAME_TYPE(self)
     63        x._parent = self._parent
     64        return x
     65   
     66    def _latex_(self):
     67        """
     68        EXAMPLES::
     69       
     70            sage: K.<t> = FunctionField(QQ)
     71            sage: latex((t+1)/t)
     72            \frac{t + 1}{t}
     73            sage: latex((t+1)/t^67)
     74            \frac{t + 1}{t^{67}}
     75            sage: latex((t+1/2)/t^67)
     76            \frac{t + \frac{1}{2}}{t^{67}}
     77        """
     78        return self._x._latex_()
     79   
     80    def matrix(self):
     81        r"""
     82        Return the matrix of multiplication by self when seeing the function field
     83        of where self is an element of as a vectorspace over its base field.
     84
     85        EXAMPLES::
     86
     87        A rational function field:
     88       
     89            sage: K.<t> = FunctionField(QQ)
     90            sage: t.matrix()
     91            [t]
     92            sage: (1/(t+1)).matrix()
     93            [1/(t + 1)]
     94
     95        Now an example in a nontrivial extension of a rational function field::
     96       
     97            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     98            sage: Y.matrix()
     99            [     0      1]
     100            [-4*x^3      x]
     101            sage: Y.matrix().charpoly('Z')
     102            Z^2 - x*Z + 4*x^3
     103
     104        An example in a relative extension, where neither function
     105        field is rational::
     106
     107            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     108            sage: M.<T> = L[]; Z.<alpha> = L.extension(T^3 - Y^2*T + x)
     109            sage: alpha.matrix()
     110            [          0           1           0]
     111            [          0           0           1]
     112            [         -x x*Y - 4*x^3           0]
     113
     114        We show that this matrix does indeed works as expected when making a
     115        vectorspace from a function field::
     116
     117            sage: K.<x>=FunctionField(QQ)
     118            sage: R.<y> = K[]
     119            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
     120            sage: V, from_V, to_V = L.vector_space()
     121            sage: w5 = to_V(w^5)
     122            sage: w5 = to_V(w^5); w5
     123            ((x^4 + 1)/x, 2*x, 0, 0, 0)
     124            sage: w4xw = to_V(w^4) * w.matrix(); w4xw
     125            ((x^4 + 1)/x, 2*x, 0, 0, 0)
     126            sage: w5 == w4xw
     127            True
     128       
     129        """
     130        if self._matrix is None:
     131            # Multiply each power of field generator on the left by this
     132            # element; make matrix whose rows are the coefficients of the
     133            # result, and transpose.
     134            K = self.parent()
     135            v = []
     136            x = K.gen()
     137            a = K(1)
     138            d = K.degree()
     139            for n in range(d):
     140                v += (a*self).list()
     141                a *= x
     142            k = K.base_ring()
     143            import sage.matrix.matrix_space
     144            M = sage.matrix.matrix_space.MatrixSpace(k, d)
     145            self._matrix = M(v)
     146        return self._matrix
     147
     148    def trace(self):
     149        """
     150        Return the trace of this function field element.
     151
     152        EXAMPLES::
     153
     154            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     155            sage: Y.trace()
     156            x
     157        """
     158        return self.matrix().trace()
     159
     160    def norm(self):
     161        """
     162        Return the norm of this function field element.
     163
     164        EXAMPLES::
     165       
     166            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     167            sage: Y.norm()
     168            4*x^3
     169
     170
     171        The norm is relative::
     172       
     173            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     174            sage: M.<T> = L[]; Z.<alpha> = L.extension(T^3 - Y^2*T + x)
     175            sage: alpha.norm()
     176            -x
     177            sage: alpha.norm().parent()
     178            Function field in Y defined by y^2 - x*y + 4*x^3
     179        """
     180        return self.matrix().determinant()
     181
     182    def characteristic_polynomial(self, *args, **kwds):
     183        """
     184        Return the characteristic polynomial of this function field
     185        element.  Give an optional input string to name the variable
     186        in the characteristic polynomial.
     187
     188        EXAMPLES::
     189
     190            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     191            sage: M.<T> = L[]; Z.<alpha> = L.extension(T^3 - Y^2*T + x)
     192            sage: x.characteristic_polynomial('W')
     193            W - x
     194            sage: Y.characteristic_polynomial('W')
     195            W^2 - x*W + 4*x^3
     196            sage: alpha.characteristic_polynomial('W')
     197            W^3 + (-x*Y + 4*x^3)*W + x
     198        """
     199        return self.matrix().characteristic_polynomial(*args, **kwds)
     200
     201    charpoly = characteristic_polynomial
     202
     203    def minimal_polynomial(self, *args, **kwds):
     204        """
     205        Return the minimal polynomial of this function field element.
     206        Give an optional input string to name the variable in the
     207        characteristic polynomial.
     208
     209        EXAMPLES::
     210
     211            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     212            sage: M.<T> = L[]; Z.<alpha> = L.extension(T^3 - Y^2*T + x)
     213            sage: x.minimal_polynomial('W')
     214            W - x
     215            sage: Y.minimal_polynomial('W')
     216            W^2 - x*W + 4*x^3
     217            sage: alpha.minimal_polynomial('W')
     218            W^3 + (-x*Y + 4*x^3)*W + x
     219        """
     220        return self.matrix().minimal_polynomial(*args, **kwds)
     221
     222    minpoly = minimal_polynomial
     223   
     224    def is_integral(self):
     225        r"""
     226        Determine if self is integral over the maximal order of the base field.
     227       
     228        EXAMPLES::
     229       
     230            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     231            sage: Y.is_integral()
     232            True
     233            sage: (Y/x).is_integral()
     234            True
     235            sage: (Y/x)^2 - (Y/x) + 4*x
     236            0
     237            sage: (Y/x^2).is_integral()
     238            False
     239            sage: f = (Y/x).minimal_polynomial('W'); f
     240            W^2 - W + 4*x           
     241        """
     242        R = self.parent().base_field().maximal_order()
     243        return all([a in R for a in self.minimal_polynomial()])
     244
     245cdef class FunctionFieldElement_polymod(FunctionFieldElement):
     246    """
     247    EXAMPLES::
     248
     249        sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     250        sage: x*Y + 1/x^3
     251        x*Y + 1/x^3       
     252    """
     253    def __init__(self, parent, x, reduce=True):
     254        """
     255        EXAMPLES::
     256
     257             sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     258             sage: type(Y)
     259             <type 'sage.rings.function_field.function_field_element.FunctionFieldElement_polymod'>             
     260        """
     261        FieldElement.__init__(self, parent)
     262        if reduce:
     263            self._x = x % self._parent.polynomial()
     264        else:
     265            self._x = x
     266   
     267    def element(self):
     268        """
     269        Return the underlying polynomial that represents this element.
     270       
     271        EXAMPLES::
     272            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     273            sage: f = Y/x^2 + x/(x^2+1); f
     274            1/x^2*Y + x/(x^2 + 1)
     275            sage: f.element()
     276            1/x^2*y + x/(x^2 + 1)
     277            sage: type(f.element())
     278            <class 'sage.rings.polynomial.polynomial_element_generic.Polynomial_generic_dense_field'>       
     279        """
     280        return self._x
     281
     282    def _repr_(self):
     283        """
     284        EXAMPLES::
     285
     286            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     287            sage: Y._repr_()
     288            'Y'
     289        """
     290        return self._x._repr(name=self.parent().variable_name())
     291       
     292    def __nonzero__(self):
     293        """
     294        EXAMPLES::
     295
     296            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     297            sage: bool(Y)
     298            True
     299            sage: bool(L(0))
     300            False
     301            sage: bool(L.coerce(L.polynomial()))
     302            False
     303        """
     304        return not not self._x
     305
     306    cdef int _cmp_c_impl(self, Element other) except -2:
     307        """
     308        EXAMPLES::
     309
     310            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     311            sage: cmp(L(0), 0)
     312            0
     313            sage: cmp(Y, L(2)) != 0
     314            True
     315        """
     316        cdef FunctionFieldElement left = <FunctionFieldElement>self
     317        cdef FunctionFieldElement right = <FunctionFieldElement>other
     318        return cmp(left._x, right._x)
     319
     320    cpdef ModuleElement _add_(self, ModuleElement right):
     321        """
     322        EXAMPLES::
     323
     324            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     325            sage: (2*Y + x/(1+x^3))  +  (3*Y + 5*x*Y)         # indirect doctest
     326            (5*x + 5)*Y + x/(x^3 + 1)
     327            sage: (Y^2 - x*Y + 4*x^3)==0                      # indirect doctest
     328            True
     329        """
     330        cdef FunctionFieldElement res = self._new_c()
     331        res._x = self._x + (<FunctionFieldElement>right)._x
     332        return res
     333
     334    cpdef ModuleElement _sub_(self, ModuleElement right):
     335        """
     336        EXAMPLES::
     337
     338            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     339            sage: (2*Y + x/(1+x^3))  -  (3*Y + 5*x*Y)         # indirect doctest
     340            (-5*x - 1)*Y + x/(x^3 + 1)
     341        """
     342        cdef FunctionFieldElement res = self._new_c()
     343        res._x = self._x - (<FunctionFieldElement>right)._x
     344        return res
     345
     346    cpdef RingElement _mul_(self, RingElement right):
     347        """
     348        EXAMPLES::
     349
     350            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     351            sage: Y  *  (3*Y + 5*x*Y)                          # indirect doctest
     352            (5*x^2 + 3*x)*Y - 20*x^4 - 12*x^3
     353        """
     354        cdef FunctionFieldElement res = self._new_c()
     355        res._x = (self._x * (<FunctionFieldElement>right)._x) % self._parent.polynomial()
     356        return res
     357
     358    cpdef RingElement _div_(self, RingElement right):
     359        """
     360        EXAMPLES::
     361
     362            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     363            sage: (2*Y + x/(1+x^3))  /  (2*Y + x/(1+x^3))       # indirect doctest
     364            1
     365            sage: 1 / (Y^2 - x*Y + 4*x^3)                       # indirect doctest
     366            Traceback (most recent call last):
     367            ...
     368            ZeroDivisionError: Cannot invert 0
     369        """
     370        return self * ~right
     371
     372    def __invert__(self):
     373        """
     374        EXAMPLES::
     375
     376            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     377            sage: a = ~(2*Y + 1/x); a                           # indirect doctest
     378            (-x^2/(8*x^5 + x^2 + 1/2))*Y + (2*x^3 + x)/(16*x^5 + 2*x^2 + 1)
     379            sage: a*(2*Y + 1/x)
     380            1
     381        """
     382        if self.is_zero():
     383            raise ZeroDivisionError, "Cannot invert 0"
     384        P = self._parent
     385        return P(self._x.xgcd(P._polynomial)[1])
     386
     387    def list(self):
     388        """
     389        EXAMPLES::
     390
     391            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     392            sage: a = ~(2*Y + 1/x); a
     393            (-x^2/(8*x^5 + x^2 + 1/2))*Y + (2*x^3 + x)/(16*x^5 + 2*x^2 + 1)
     394            sage: a.list()
     395            [(2*x^3 + x)/(16*x^5 + 2*x^2 + 1), -x^2/(8*x^5 + x^2 + 1/2)]
     396            sage: (x*Y).list()
     397            [0, x]
     398        """
     399        return self._x.padded_list(self.parent().degree())
     400       
     401
     402cdef class FunctionFieldElement_rational(FunctionFieldElement):
     403    """
     404    EXAMPLES::
     405   
     406        sage: FunctionField(QQ, 't')
     407        Rational function field in t over Rational Field
     408    """
     409    def __init__(self, parent, x, reduce=True):
     410        """
     411        EXAMPLES::
     412       
     413            sage: FunctionField(QQ,'t').gen()^3
     414            t^3
     415        """
     416        FieldElement.__init__(self, parent)
     417        self._x = x
     418 
     419    # nonoptimized
     420
     421    def element(self):
     422        """
     423        Return the underlying fraction field element that represents this element.
     424
     425        EXAMPLES::
     426
     427            sage: R.<a> = FunctionField(GF(7))
     428            sage: a.element()
     429            a
     430            sage: type(a.element())
     431            <type 'sage.rings.fraction_field_FpT.FpTElement'>       
     432
     433            sage: R.<a> = FunctionField(GF(131101))
     434            sage: a.element()
     435            a
     436            sage: type(a.element())
     437            <class 'sage.rings.fraction_field_element.FractionFieldElement_1poly_field'>
     438        """
     439        return self._x
     440
     441    def list(self):
     442        """
     443        EXAMPLES::
     444
     445            sage: K.<t> = FunctionField(QQ)
     446            sage: t.list()
     447            [t]
     448        """
     449        return [self]
     450
     451    def _repr_(self):
     452        """
     453        EXAMPLES::
     454
     455            sage: K.<t> = FunctionField(QQ)
     456            sage: t._repr_()
     457            't'
     458        """
     459        return repr(self._x)
     460       
     461    def __nonzero__(self):
     462        """
     463        EXAMPLES::
     464
     465            sage: K.<t> = FunctionField(QQ)
     466            sage: bool(t)
     467            True
     468            sage: bool(K(0))
     469            False
     470            sage: bool(K(1))
     471            True
     472        """
     473        return not not self._x
     474
     475    cdef int _cmp_c_impl(self, Element other) except -2:
     476        """
     477        EXAMPLES::
     478
     479            sage: K.<t> = FunctionField(QQ)
     480            sage: cmp(t, 0)
     481            1
     482            sage: cmp(t, t^2)
     483            -1
     484        """
     485        cdef int c = cmp(type(self), type(other))
     486        if c: return c
     487        cdef FunctionFieldElement left = <FunctionFieldElement>self
     488        cdef FunctionFieldElement right = <FunctionFieldElement>other
     489        c = cmp(left._parent, right._parent)
     490        return c or cmp(left._x, right._x)
     491
     492    cpdef ModuleElement _add_(self, ModuleElement right):
     493        """
     494        EXAMPLES::
     495       
     496            sage: K.<t> = FunctionField(QQ)
     497            sage: t + (3*t^3)                      # indirect doctest
     498            3*t^3 + t
     499        """
     500        cdef FunctionFieldElement res = self._new_c()
     501        res._x = self._x + (<FunctionFieldElement>right)._x
     502        return res
     503
     504    cpdef ModuleElement _sub_(self, ModuleElement right):
     505        """
     506        EXAMPLES::
     507
     508
     509            sage: K.<t> = FunctionField(QQ)
     510            sage: t - (3*t^3)                      # indirect doctest
     511            -3*t^3 + t
     512        """
     513        cdef FunctionFieldElement res = self._new_c()
     514        res._x = self._x - (<FunctionFieldElement>right)._x
     515        return res
     516
     517    cpdef RingElement _mul_(self, RingElement right):
     518        """
     519        EXAMPLES::
     520
     521            sage: K.<t> = FunctionField(QQ)
     522            sage: (t+1) * (t^2-1)                  # indirect doctest
     523            t^3 + t^2 - t - 1
     524        """
     525        cdef FunctionFieldElement res = self._new_c()
     526        res._x = self._x * (<FunctionFieldElement>right)._x
     527        return res
     528
     529    cpdef RingElement _div_(self, RingElement right):
     530        """
     531        EXAMPLES::
     532
     533            sage: K.<t> = FunctionField(QQ)
     534            sage: (t+1) / (t^2 - 1)                # indirect doctest
     535            1/(t - 1)
     536        """
     537        cdef FunctionFieldElement res = self._new_c()
     538        res._parent = self._parent.fraction_field()
     539        res._x = self._x / (<FunctionFieldElement>right)._x
     540        return res
     541
     542    def numerator(self):
     543        """
     544        EXAMPLES::
     545
     546            sage: K.<t> = FunctionField(QQ)
     547            sage: f = (t+1) / (t^2 - 1/3); f
     548            (t + 1)/(t^2 - 1/3)
     549            sage: f.numerator()
     550            t + 1
     551        """
     552        return self._x.numerator()
     553
     554    def denominator(self):
     555        """
     556        EXAMPLES::
     557
     558            sage: K.<t> = FunctionField(QQ)
     559            sage: f = (t+1) / (t^2 - 1/3); f
     560            (t + 1)/(t^2 - 1/3)
     561            sage: f.denominator()
     562            t^2 - 1/3
     563        """
     564        return self._x.denominator()
     565   
     566    def valuation(self, v):
     567        """
     568        EXAMPLES::
     569       
     570            sage: K.<t> = FunctionField(QQ)
     571            sage: f = (t-1)^2 * (t+1) / (t^2 - 1/3)^3
     572            sage: f.valuation(t-1)
     573            2
     574            sage: f.valuation(t)
     575            0
     576            sage: f.valuation(t^2 - 1/3)
     577            -3
     578        """
     579        R = self._parent._ring
     580        return self._x.valuation(R(self._parent(v)._x))
     581   
     582    def is_square(self):
     583        """
     584        Returns whether self is a square.
     585       
     586        EXAMPLES::
     587           
     588            sage: K.<t> = FunctionField(QQ)
     589            sage: t.is_square()
     590            False
     591            sage: (t^2/4).is_square()
     592            True
     593            sage: f = 9 * (t+1)^6 / (t^2 - 2*t + 1); f.is_square()
     594            True
     595           
     596            sage: K.<t> = FunctionField(GF(5))
     597            sage: (-t^2).is_square()
     598            True
     599            sage: (-t^2).sqrt()
     600            2*t
     601        """
     602        return self._x.is_square()
     603   
     604    def sqrt(self, all=False):
     605        """
     606        Returns the square root of self.
     607       
     608        EXMPLES::
     609       
     610            sage: K.<t> = FunctionField(QQ)
     611            sage: f = t^2 - 2 + 1/t^2; f.sqrt()
     612            (t^2 - 1)/t
     613            sage: f = t^2; f.sqrt(all=True)
     614            [t, -t]
     615           
     616        TESTS::
     617       
     618            sage: K(4/9).sqrt()
     619            2/3
     620            sage: K(0).sqrt(all=True)
     621            [0]
     622        """
     623        if all:
     624            return [self._parent(r) for r in self._x.sqrt(all=True)]
     625        else:
     626            return self._parent(self._x.sqrt())
     627
     628    def factor(self):
     629        """
     630        Factor this rational function.
     631       
     632        EXAMPLES::
     633
     634            sage: K.<t> = FunctionField(QQ)
     635            sage: f = (t+1) / (t^2 - 1/3)
     636            sage: f.factor()
     637            (t + 1) * (t^2 - 1/3)^-1
     638            sage: (7*f).factor()
     639            (7) * (t + 1) * (t^2 - 1/3)^-1
     640            sage: ((7*f).factor()).unit()
     641            7
     642            sage: (f^3).factor()
     643            (t + 1)^3 * (t^2 - 1/3)^-3
     644        """
     645        P = self.parent()
     646        F = self._x.factor()
     647        from sage.structure.factorization import Factorization
     648        return Factorization([(P(a),e) for a,e in F], unit=F.unit())
     649
     650    def inverse_mod(self, I):
     651        r"""
     652        Return an inverse of self modulo the integral ideal `I`, if
     653        defined, i.e., if `I` and self together generate the unit
     654        ideal.
     655
     656        EXAMPLES::
     657
     658            sage: R.<x> = FunctionField(QQ)
     659            sage: S = R.maximal_order(); I = S.ideal(x^2+1)
     660            sage: t = S(x+1).inverse_mod(I); t
     661            -1/2*x + 1/2
     662            sage: (t*(x+1) - 1) in I
     663            True           
     664        """
     665        assert  len(I.gens()) == 1
     666        f = I.gens()[0]._x
     667        assert f.denominator() == 1
     668        assert self._x.denominator() == 1
     669        return self.parent()(self._x.numerator().inverse_mod(f.numerator()))
  • new file sage/rings/function_field/function_field_ideal.py

    diff --git a/sage/rings/function_field/function_field_ideal.py b/sage/rings/function_field/function_field_ideal.py
    new file mode 100644
    - +  
     1from sage.rings.ideal import Ideal_generic
     2
     3class FunctionFieldIdeal(Ideal_generic):
     4    """
     5    A fractional ideal of a function field.
     6
     7    EXAMPLES::
     8
     9        sage: R.<x> = FunctionField(GF(7))
     10        sage: S = R.maximal_order(); I = S.ideal(x^3+1)
     11        sage: isinstance(I, sage.rings.function_field.function_field_ideal.FunctionFieldIdeal)
     12        True   
     13    """
     14    pass
     15
     16class FunctionFieldIdeal_module(FunctionFieldIdeal):
     17    """
     18    A fractional ideal specified by a finitely generated module over
     19    the integers of the base field.
     20
     21    EXAMPLES::
     22
     23    An ideal in a rational function field::
     24
     25        sage: R.<x> = FunctionField(QQ); S.<y> = R[]
     26        sage: L.<y> = R.extension(y^2 - x^3 - 1); M = L.equation_order()   
     27        sage: I = M.ideal(y)
     28        sage: I
     29        Ideal (x^3 + 1, -y) of Order in Function field in y defined by y^2 - x^3 - 1
     30        sage: I^2
     31        Ideal (x^3 + 1, (-x^3 - 1)*y) of Order in Function field in y defined by y^2 - x^3 - 1   
     32    """
     33    def __init__(self, ring, module):
     34        """
     35        INPUT:
     36
     37            - ``ring`` -- an order in a function field
     38            - ``module`` -- a module
     39
     40        EXAMPLES::
     41
     42            sage: R.<x> = FunctionField(QQ); S.<y> = R[]
     43            sage: L.<y> = R.extension(y^2 - x^3 - 1); M = L.equation_order()   
     44            sage: I = M.ideal(y)
     45            sage: type(I)
     46            <class 'sage.rings.function_field.function_field_ideal.FunctionFieldIdeal_module'>
     47        """
     48        self._ring = ring
     49        self._module = module
     50        self._structure = ring.fraction_field().vector_space()
     51        V, from_V, to_V = self._structure
     52        gens = tuple([from_V(a) for a in module.basis()])
     53        Ideal_generic.__init__(self, ring, gens, coerce=False)
     54
     55    def __contains__(self, x):
     56        """
     57        Return True if x is in this ideal.
     58
     59        EXAMPLES::
     60
     61            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     62            sage: L.<y> = R.extension(y^2 - x^3 - 1); M = L.equation_order()
     63            sage: I = M.ideal_with_gens_over_base([1, y]);  I
     64            Ideal (1, y) of Order in Function field in y defined by y^2 + 6*x^3 + 6
     65            sage: y in I
     66            True
     67            sage: y/x in I
     68            False
     69            sage: y^2 - 2 in I
     70            True
     71        """
     72        return self._structure[2](x) in self._module
     73
     74    def module(self):
     75        """
     76        Return module over the maximal order of the base field that
     77        underlies self.
     78
     79        The formation of this module is compatible with the vector
     80        space corresponding to the function field.
     81
     82        OUTPUT:
     83
     84            - a module over the maximal order of the base field of self
     85
     86        EXAMPLES::
     87
     88            sage: R.<x> = FunctionField(GF(7))
     89            sage: S = R.maximal_order(); S
     90            Maximal order in Rational function field in x over Finite Field of size 7
     91            sage: R.polynomial_ring()
     92            Univariate Polynomial Ring in x over Rational function field in x over Finite Field of size 7
     93            sage: I = S.ideal_with_gens_over_base([x^2 + 1, x*(x^2+1)])
     94            sage: I.gens()
     95            (x^2 + 1,)
     96            sage: I.module()
     97            Free module of degree 1 and rank 1 over Maximal order in Rational function field in x over Finite Field of size 7
     98            User basis matrix:
     99            [x^2 + 1]
     100            sage: V, from_V, to_V = R.vector_space(); V
     101            Vector space of dimension 1 over Rational function field in x over Finite Field of size 7
     102            sage: I.module().is_submodule(V)
     103            True       
     104        """
     105        return self._module
     106
     107    def __add__(self, other):
     108        """
     109        Add together two ideals.
     110       
     111        EXAMPLES::
     112       
     113            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     114            sage: L.<y> = R.extension(y^2 - x^3 - 1); M = L.equation_order()   
     115            sage: I = M.ideal(y); J = M.ideal(y+1)
     116            sage: Z = I + J; Z
     117            Ideal (y + 1, 6*y) of Order in Function field in y defined by y^2 + 6*x^3 + 6
     118            sage: 1 in Z
     119            True
     120            sage: M.ideal(y^2) + M.ideal(y^3) == M.ideal(y^2,y^3)
     121            True
     122        """
     123        if not isinstance(other, FunctionFieldIdeal_module):
     124            other = self.ring().ideal(other)
     125        return FunctionFieldIdeal_module(self.ring(), self.module() + other.module())
     126
     127    def intersection(self, other):
     128        """
     129        Return the intersection of the ideals self and other.
     130       
     131        EXAMPLES::
     132
     133            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     134            sage: L.<y> = R.extension(y^2 - x^3 - 1); M = L.equation_order()   
     135            sage: I = M.ideal(y^3); J = M.ideal(y^2)
     136            sage: Z = I.intersection(J); Z
     137            Ideal (x^6 + 2*x^3 + 1, (6*x^3 + 6)*y) of Order in Function field in y defined by y^2 + 6*x^3 + 6
     138            sage: y^2 in Z
     139            False
     140            sage: y^3 in Z
     141            True
     142        """
     143        if not isinstance(other, FunctionFieldIdeal_module):
     144            other = self.ring().ideal(other)
     145        if self.ring() != other.ring():
     146            raise ValueError, "rings must be the same"
     147        return FunctionFieldIdeal_module(self.ring(), self.module().intersection(other.module()))
     148
     149    def __cmp__(self, other):
     150        """
     151        Compare self and other.
     152       
     153        EXAMPLES::
     154
     155            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     156            sage: L.<y> = R.extension(y^2 - x^3 - 1)
     157            sage: M = L.equation_order()   
     158            sage: I = M.ideal(y*(y+1)); J = M.ideal((y^2-2)*(y+1))
     159            sage: I+J == J+I            # indirect test
     160            True
     161            sage: I == J
     162            False
     163            sage: I < J
     164            True
     165            sage: J < I
     166            False       
     167        """
     168        if not isinstance(other, FunctionFieldIdeal_module):
     169            other = self.ring().ideal(other)
     170        if self.ring() != other.ring():
     171            raise ValueError, "rings must be the same"
     172        return cmp(self.module(), other.module())
     173
     174    def __invert__(self):
     175        """
     176        Return the inverse of this fractional ideal.
     177
     178        EXAMPLES::
     179
     180            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     181            sage: L.<y> = R.extension(y^2 - x^3 - 1); M = L.equation_order()   
     182            sage: I = M.ideal(y)
     183            sage: I.__invert__()
     184            Ideal (6, (1/(x^3 + 1))*y) of Order in Function field in y defined by y^2 + 6*x^3 + 6
     185            sage: I^(-1)
     186            Ideal (6, (1/(x^3 + 1))*y) of Order in Function field in y defined by y^2 + 6*x^3 + 6
     187            sage: I.__invert__() * I
     188            Ideal (1, y) of Order in Function field in y defined by y^2 + 6*x^3 + 6
     189        """
     190        if len(self.gens()) == 0:
     191            raise ZeroDivisionError
     192
     193        # NOTE: If  I = (g0, ..., gn), then {x : x*I is in R}
     194        # is the intersection over i of {x : x*gi is in R}
     195        # Thus (I + J)^(-1) = I^(-1) intersect J^(-1).
     196       
     197        G = self.gens()
     198        R = self.ring()
     199        inv = R.ideal(~G[0])
     200        for g in G[1:]:
     201            inv = inv.intersection(R.ideal(~g))
     202        return inv
     203
     204def ideal_with_gens(R, gens):
     205    """
     206    Return fractional ideal in the order of R with given generators
     207    over R.
     208
     209    EXAMPLES::
     210
     211        sage: R.<x> = FunctionField(QQ); S.<y> = R[]
     212        sage: L.<y> = R.extension(y^2 - x^3 - 1); M = L.equation_order()   
     213        sage: sage.rings.function_field.function_field_ideal.ideal_with_gens(M, [y])
     214        Ideal (x^3 + 1, -y) of Order in Function field in y defined by y^2 - x^3 - 1
     215    """
     216    K = R.fraction_field()
     217    return ideal_with_gens_over_base(R, [b*K(g) for b in R.basis() for g in gens])
     218   
     219
     220def ideal_with_gens_over_base(R, gens):
     221    """
     222    Return fractional ideal in the given order R with given generators
     223    over the maximal order of the base field.
     224
     225    EXAMPLES::
     226
     227        sage: R.<x> = FunctionField(QQ); S.<y> = R[]
     228        sage: L.<y> = R.extension(y^2 - x^3 - 1); M = L.equation_order()   
     229        sage: sage.rings.function_field.function_field_ideal.ideal_with_gens_over_base(M, [x^3+1,-y])
     230        Ideal (x^3 + 1, -y) of Order in Function field in y defined by y^2 - x^3 - 1   
     231    """
     232    K = R.fraction_field()
     233    V, from_V, to_V = K.vector_space()
     234
     235    # We handle the case of a rational function field separately,
     236    # since this is the base case and is used, e.g,. internally
     237    # by the linear algebra Hermite form code.
     238    import function_field_order
     239    if isinstance(R, function_field_order.FunctionFieldOrder_rational):
     240        try:
     241            v = R._ring.ideal([x.element() for x in gens]).gens_reduced()
     242            assert len(v) == 1
     243            basis = [to_V(v[0])]
     244            M = V.span_of_basis(basis, check=False, already_echelonized=True, base_ring=R)
     245        except Exception, msg:
     246            print msg   # TODO --for debugging
     247            raise
     248    else:
     249        # General case
     250        S = V.base_field().maximal_order()
     251        M = V.span([to_V(b) for b in gens], base_ring=S)
     252
     253    return FunctionFieldIdeal_module(R, M)
  • new file sage/rings/function_field/function_field_order.py

    diff --git a/sage/rings/function_field/function_field_order.py b/sage/rings/function_field/function_field_order.py
    new file mode 100644
    - +  
     1"""
     2Orders in Function Fields
     3"""
     4
     5from sage.structure.parent_gens import ParentWithGens
     6
     7from sage.rings.ring import IntegralDomain, PrincipalIdealDomain
     8
     9from sage.rings.ideal import is_Ideal
     10
     11class FunctionFieldOrder(IntegralDomain):
     12    def __init__(self, fraction_field):
     13        """
     14        EXAMPLES::
     15
     16            sage: R = FunctionField(QQ,'y').maximal_order()
     17            sage: isinstance(R, sage.rings.function_field.function_field_order.FunctionFieldOrder)
     18            True
     19        """
     20        self._fraction_field = fraction_field
     21
     22    def _repr_(self):
     23        """
     24        EXAMPLES::
     25
     26            sage: FunctionField(QQ,'y').maximal_order()._repr_()
     27            'Maximal order in Rational function field in y over Rational Field'
     28        """
     29        return "Order in %s"%self.fraction_field()
     30
     31    def is_finite(self):
     32        """
     33        EXAMPLES::
     34
     35            sage: FunctionField(QQ,'y').maximal_order().is_finite()
     36            False
     37        """
     38        return False
     39
     40    def is_field(self, proof=True):
     41        """
     42        EXAMPLES::
     43
     44            sage: FunctionField(QQ,'y').maximal_order().is_field()
     45            False
     46        """
     47        return False
     48
     49    def is_noetherian(self):
     50        """
     51        Return True, since orders in function fields are noetherian.
     52       
     53        EXAMPLES::
     54
     55            sage: FunctionField(QQ,'y').maximal_order().is_noetherian()
     56            True
     57        """
     58        return True
     59
     60    def fraction_field(self):
     61        """
     62        Returns the function field in wich this is an order
     63
     64        EXAMPLES::
     65
     66            sage: FunctionField(QQ,'y').maximal_order().fraction_field()
     67            Rational function field in y over Rational Field
     68        """
     69        return self._fraction_field
     70
     71    function_field = fraction_field
     72   
     73    def ideal_with_gens_over_base(self, gens):
     74        """
     75        Return the fractional ideal with given generators over the
     76        maximal ideal of the base field.  That this is really an ideal
     77        is not checked.
     78
     79        INPUT:
     80
     81            - ``basis`` -- list of elements that are a basis for the
     82              ideal over the maximal order of the base field
     83           
     84        EXAMPLES::
     85
     86        We construct an ideal in a rational function field::
     87       
     88            sage: R.<y> = FunctionField(QQ)
     89            sage: S = R.maximal_order()
     90            sage: I = S.ideal_with_gens_over_base([y]); I
     91            Ideal (y) of Maximal order in Rational function field in y over Rational Field
     92            sage: I*I
     93            Ideal (y^2) of Maximal order in Rational function field in y over Rational Field
     94
     95        We construct some ideals in a nontrivial function field::
     96
     97            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     98            sage: L.<y> = R.extension(y^2 - x^3 - 1)
     99            sage: M = L.equation_order(); M
     100            Order in Function field in y defined by y^2 + 6*x^3 + 6
     101            sage: I = M.ideal_with_gens_over_base([1, y]);  I
     102            Ideal (1, y) of Order in Function field in y defined by y^2 + 6*x^3 + 6
     103            sage: I.module()
     104            Free module of degree 2 and rank 2 over Maximal order in Rational function field in x over Finite Field of size 7
     105            Echelon basis matrix:
     106            [1 0]
     107            [0 1]
     108        """
     109        from function_field_ideal import ideal_with_gens_over_base
     110        return ideal_with_gens_over_base(self, [self(a) for a in gens])
     111
     112    def ideal(self, *gens):
     113        """
     114        Return the fractional ideal generated by the element gens or
     115        the elements in gens if gens is a list.
     116
     117        EXAMPLES::
     118
     119            sage: R.<y> = FunctionField(QQ)
     120            sage: S = R.maximal_order()
     121            sage: S.ideal(y)
     122            Ideal (y) of Maximal order in Rational function field in y over Rational Field
     123
     124        A fractional ideal of a nontrivial extension::
     125
     126            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     127            sage: L.<y> = R.extension(y^2 - x^3 - 1)
     128            sage: M = L.equation_order()
     129            sage: M.ideal(1/y)
     130            Ideal (1, (6/(x^3 + 1))*y) of Order in Function field in y defined by y^2 + 6*x^3 + 6       
     131        """
     132        if len(gens) == 1:
     133            gens = gens[0]
     134            if not isinstance(gens, (list, tuple)):
     135                gens = [gens]
     136        from function_field_ideal import ideal_with_gens
     137        return ideal_with_gens(self, gens)
     138
     139
     140       
     141   
     142
     143class FunctionFieldOrder_basis(FunctionFieldOrder):
     144    """
     145    An order given by a basis over the maximal order of the base
     146    field.
     147    """
     148    def __init__(self, basis, check=True):
     149        """
     150        EXAMPLES::
     151
     152            sage: K.<x> = FunctionField(GF(7)); R.<y> = K[]; L.<Y> = K.extension(y^4 + x*y + 4*x + 1); S = L.equation_order()
     153            sage: S
     154            Order in Function field in Y defined by y^4 + x*y + 4*x + 1
     155            sage: type(S)
     156            <class 'sage.rings.function_field.function_field_order.FunctionFieldOrder_basis_with_category'>
     157
     158        The basis only defines an order if the module it generates is closed under multiplication
     159         and contains the identity element. This is only checked when check=True ::
     160
     161            sage: K.<x> = FunctionField(QQ)
     162            sage: R.<y> = K[]
     163            sage: L.<w> = K.extension(y^5 - (x^3 + 2*x*y + 1/x));
     164            sage: w.is_integral()
     165            False
     166            sage: L.order(w)
     167            Traceback (most recent call last):
     168            ...
     169            ValueError: The module generated by basis [1, w, w^2, w^3, w^4] must be closed under multiplication
     170           
     171        The basis also has to be linear independent and of the same rank as the degree of the function field of it's elements::
     172
     173            sage: L.order(L(x))
     174            Traceback (most recent call last):
     175            ...
     176            ValueError: Basis [1, x, x^2, x^3, x^4] is not linear independent
     177            sage: sage.rings.function_field.function_field_order.FunctionFieldOrder_basis([w,w,w^3,w^4,w^5])
     178            Traceback (most recent call last):
     179            ...
     180            ValueError: Basis [w, w, w^3, w^4, 2*x*w + (x^4 + 1)/x] is not linear independent
     181       
     182
     183        """
     184        if len(basis) == 0:
     185            raise ValueError, "basis must have positive length"
     186       
     187        fraction_field = basis[0].parent()
     188        if len(basis) != fraction_field.degree():
     189            raise ValueError, "length of basis must equal degree of field"
     190       
     191        FunctionFieldOrder.__init__(self, fraction_field)
     192       
     193        self._basis = tuple(basis)
     194        V, fr, to = fraction_field.vector_space()
     195        R = fraction_field.base_field().maximal_order()
     196        self._module = V.span([to(b) for b in basis], base_ring=R)
     197        self._ring = fraction_field.polynomial_ring()
     198        self._populate_coercion_lists_(coerce_list=[self._ring])
     199        if check:
     200            if self._module.rank() != fraction_field.degree():
     201                raise ValueError, "Basis %s is not linear independent"%(basis)
     202            if not to(fraction_field(1)) in self._module:
     203                raise ValueError, "The identity element must be in the module spanned by basis %s"%(basis)
     204            if not all(to(a*b) in self._module for a in basis for b in basis):
     205                raise ValueError, "The module generated by basis %s must be closed under multiplication"%(basis)
     206        IntegralDomain.__init__(self, self, names = fraction_field.variable_names(), normalize = False)
     207
     208    def _element_constructor_(self, f, check=True):
     209        """
     210        EXAMPLES::
     211
     212            sage: R.<y> = FunctionField(QQ)
     213            sage: R.maximal_order()._element_constructor_(y)
     214            y
     215       
     216        If check=True test if the element is indeed in the order.
     217        """
     218        fraction_field=self.fraction_field()
     219       
     220        if f.parent() is fraction_field:
     221            f = f.element()
     222        f = self._ring(f)
     223        if check:
     224            V, fr, to = fraction_field.vector_space()
     225            f_vector = to(fraction_field(f))
     226            if not f_vector in self._module:
     227                raise ValueError, "%s is not an element of %s"%(f_vector,self)
     228        return fraction_field._element_class(self, f)
     229
     230    def fraction_field(self):
     231        """
     232        EXAMPLES::
     233
     234            sage: K.<x> = FunctionField(GF(7)); R.<y> = K[]; L.<Y> = K.extension(y^4 + x*y + 4*x + 1); S = L.equation_order()           
     235            sage: S.fraction_field()
     236            Function field in Y defined by y^4 + x*y + 4*x + 1
     237        """
     238        return self._fraction_field
     239
     240    def polynomial(self):
     241        """
     242        Returns the defining polynomial of the function field of which this is an order.
     243       
     244        EXAMPLES::
     245
     246            sage: K.<x> = FunctionField(GF(7)); R.<y> = K[]; L.<Y> = K.extension(y^4 + x*y + 4*x + 1); S = L.equation_order()           
     247            sage: S.polynomial()
     248            y^4 + x*y + 4*x + 1
     249       
     250        """
     251        return self._fraction_field.polynomial()
     252
     253
     254    def basis(self):
     255        """
     256        EXAMPLES::
     257
     258            sage: K.<x> = FunctionField(GF(7)); R.<y> = K[]; L.<Y> = K.extension(y^4 + x*y + 4*x + 1); S = L.equation_order()           
     259            sage: S.basis()
     260            (1, Y, Y^2, Y^3)
     261        """
     262        return self._basis
     263
     264    def free_module(self):
     265        """
     266        EXAMPLES::
     267
     268            sage: K.<x> = FunctionField(GF(7)); R.<y> = K[]; L.<Y> = K.extension(y^4 + x*y + 4*x + 1); S = L.equation_order()
     269            sage: S.free_module()
     270            Free module of degree 4 and rank 4 over Maximal order in Rational function field in x over Finite Field of size 7
     271            Echelon basis matrix:
     272            [1 0 0 0]
     273            [0 1 0 0]
     274            [0 0 1 0]
     275            [0 0 0 1]       
     276        """
     277        return self._module
     278
     279##     def polynomial_quotient_ring(self):
     280##         """
     281##         Return a quotient of a (possibly multivariate) polynomial ring
     282##         that is isomorphic to self, along with morphisms back and
     283##         forth.
     284##         """
     285##         raise NotImplementedError
     286   
     287
     288import function_field_element   
     289       
     290class FunctionFieldOrder_rational(PrincipalIdealDomain, FunctionFieldOrder):
     291    """
     292    The maximal order in a rational function field.
     293    """
     294    def __init__(self, function_field):
     295        """
     296        EXAMPLES::
     297       
     298            sage: K.<t> = FunctionField(GF(19)); K
     299            Rational function field in t over Finite Field of size 19
     300            sage: R = K.maximal_order(); R
     301            Maximal order in Rational function field in t over Finite Field of size 19
     302            sage: type(R)
     303            <class 'sage.rings.function_field.function_field_order.FunctionFieldOrder_rational_with_category'>
     304        """
     305        FunctionFieldOrder.__init__(self, function_field)
     306        IntegralDomain.__init__(self, self, names = function_field.variable_names(), normalize = False)
     307        self._ring = function_field._ring
     308        self._populate_coercion_lists_(coerce_list=[self._ring])
     309        self._gen = self(self._ring.gen())
     310        self._basis = (self(1),)
     311
     312    def basis(self):
     313        """
     314        Return basis (=1) for this order as a module over the polynomial ring.
     315       
     316        EXAMPLES::
     317
     318            sage: K.<t> = FunctionField(GF(19))
     319            sage: M = K.maximal_order()
     320            sage: M.basis()
     321            (1,)
     322            sage: parent(M.basis()[0])
     323            Maximal order in Rational function field in t over Finite Field of size 19
     324        """
     325        return self._basis
     326
     327    def ideal(self, *gens):
     328        """
     329        Return the fractional ideal generated by the element gens or
     330        the elements in gens if gens is a list.
     331
     332        EXAMPLES::
     333
     334            sage: R.<y> = FunctionField(QQ)
     335            sage: S = R.maximal_order()
     336            sage: S.ideal(y)
     337            Ideal (y) of Maximal order in Rational function field in y over Rational Field
     338
     339        A fractional ideal of a nontrivial extension::
     340
     341            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     342            sage: L.<y> = R.extension(y^2 - x^3 - 1)
     343            sage: M = L.equation_order()
     344            sage: M.ideal(1/y)
     345            Ideal (1, (6/(x^3 + 1))*y) of Order in Function field in y defined by y^2 + 6*x^3 + 6
     346
     347        A non-principal ideal::
     348
     349            sage: R.<x> = FunctionField(GF(7))
     350            sage: S = R.maximal_order()
     351            sage: S.ideal(x^3+1,x^3+6)
     352            Ideal (1) of Maximal order in Rational function field in x over Finite Field of size 7
     353            sage: S.ideal((x^2+1)*(x^3+1),(x^3+6)*(x^2+1))
     354            Ideal (x^2 + 1) of Maximal order in Rational function field in x over Finite Field of size 7   
     355        """
     356        if len(gens) == 1:
     357            gens = gens[0]
     358            if not isinstance(gens, (list, tuple)):
     359                if is_Ideal(gens):
     360                    gens = gens.gens()
     361                else:
     362                    gens = [gens]
     363        from function_field_ideal import ideal_with_gens
     364        return ideal_with_gens(self, gens)
     365
     366    def _repr_(self):
     367        """
     368        EXAMPLES::
     369           
     370            sage: FunctionField(QQ,'y').maximal_order()._repr_()
     371            'Maximal order in Rational function field in y over Rational Field'
     372        """
     373        return "Maximal order in %s"%self.fraction_field()
     374
     375    def gen(self, n=0):
     376        """
     377        EXAMPLES::
     378
     379            sage: R = FunctionField(QQ,'y').maximal_order(); R.gen()
     380            y
     381            sage: R.gen(1)
     382            Traceback (most recent call last):
     383            ...
     384            IndexError: Only one generator.
     385        """
     386        if n != 0: raise IndexError, "Only one generator."
     387        return self._gen
     388
     389    def ngens(self):
     390        """
     391        EXAMPLES::
     392
     393            sage: R = FunctionField(QQ,'y').maximal_order(); R.ngens()
     394            1
     395        """
     396        return 1
     397
     398    def _element_constructor_(self, f):
     399        """
     400        EXAMPLES::
     401
     402            sage: R.<y> = FunctionField(QQ)
     403            sage: R.maximal_order()._element_constructor_(y)
     404            y
     405        """
     406        # HUGE TODO: have to check that f is really in self!!
     407       
     408        if f.parent() is self.fraction_field():
     409            f = f.element()
     410        if f.parent() is self._ring:
     411            return function_field_element.FunctionFieldElement_rational(self, f)
     412        return function_field_element.FunctionFieldElement_rational(self, self._ring(f))
     413
     414##     def polynomial_quotient_ring(self):
     415##         """
     416##         Return a quotient of a (possibly multivariate) polynomial ring
     417##         that is isomorphic to self, along with morphisms back and
     418##         forth.
     419
     420##         EXAMPLES::
     421##         """
     422##         return self._ring
     423
     424   
     425       
     426       
  • new file sage/rings/function_field/maps.py

    diff --git a/sage/rings/function_field/maps.py b/sage/rings/function_field/maps.py
    new file mode 100644
    - +  
     1r"""
     2
     3"""
     4
     5from sage.categories.map import Map
     6from sage.categories.homset import Hom
     7
     8from function_field_order import FunctionFieldOrder
     9
     10class FunctionFieldIsomorphism(Map):
     11    r"""
     12    A base class for various isomorphisms between function fields and
     13    vector spaces.
     14
     15    EXAMPLES::
     16
     17        sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     18        sage: V, f, t = L.vector_space()
     19        sage: isinstance(f, sage.rings.function_field.maps.FunctionFieldIsomorphism)
     20        True
     21    """
     22    def _repr_type(self):
     23        """
     24        Return the type of this map (an isomorphism), for the purposes of printing out self. 
     25       
     26        EXAMPLES::
     27
     28            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     29            sage: V, f, t = L.vector_space()
     30            sage: f._repr_type()
     31            'Isomorphism'
     32        """
     33        return "Isomorphism"
     34
     35    def is_injective(self):
     36        """
     37        Return True, since this isomorphism is injective.
     38       
     39        EXAMPLES::
     40
     41            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     42            sage: V, f, t = L.vector_space()           
     43            sage: f.is_injective()
     44            True
     45        """
     46        return True
     47
     48    def is_surjective(self):
     49        """
     50        Return True, since this isomorphism is surjective.
     51       
     52        EXAMPLES::
     53
     54            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     55            sage: V, f, t = L.vector_space()           
     56            sage: f.is_surjective()
     57            True
     58        """
     59        return True
     60
     61class MapVectorSpaceToFunctionField(FunctionFieldIsomorphism):
     62    r"""
     63    An isomorphism from a vector space and a function field.
     64   
     65    EXAMPLES:
     66
     67        sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     68        sage: V, f, t = L.vector_space(); f
     69        Isomorphism map:
     70          From: Vector space of dimension 2 over Rational function field in x over Rational Field
     71          To:   Function field in Y defined by y^2 - x*y + 4*x^3
     72    """
     73    def __init__(self, V, K):
     74        """
     75        EXAMPLES::
     76       
     77            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     78            sage: V, f, t = L.vector_space(); type(f)
     79            <class 'sage.rings.function_field.maps.MapVectorSpaceToFunctionField'>
     80        """
     81        self._V = V
     82        self._K = K
     83        self._R = K.polynomial_ring()
     84        FunctionFieldIsomorphism.__init__(self, Hom(V, K))
     85
     86    def _call_(self, v):
     87        """
     88        EXAMPLES::
     89
     90            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     91            sage: V, f, t = L.vector_space()                       
     92            sage: f(x*V.0 + (1/x^3)*V.1)         # indirect doctest
     93            1/x^3*Y + x
     94        """
     95        f = self._R(self._V(v).list())
     96        return self._K(f)
     97
     98    def domain(self):
     99        """
     100        EXAMPLES::
     101
     102            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     103            sage: V, f, t = L.vector_space()                                   
     104            sage: f.domain()
     105            Vector space of dimension 2 over Rational function field in x over Rational Field
     106        """
     107        return self._V
     108
     109    def codomain(self):
     110        """
     111        EXAMPLES::
     112
     113            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     114            sage: V, f, t = L.vector_space()                                   
     115            sage: f.codomain()
     116            Function field in Y defined by y^2 - x*y + 4*x^3
     117        """
     118        return self._K
     119
     120
     121class MapFunctionFieldToVectorSpace(FunctionFieldIsomorphism):
     122    """
     123    An isomorphism from a function field to a vector space.
     124   
     125    EXAMPLES::
     126
     127        sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     128        sage: V, f, t = L.vector_space(); t
     129        Isomorphism map:
     130          From: Function field in Y defined by y^2 - x*y + 4*x^3
     131          To:   Vector space of dimension 2 over Rational function field in x over Rational Field
     132    """
     133    def __init__(self, K, V):
     134        """
     135        EXAMPLES::
     136
     137            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     138            sage: V, f, t = L.vector_space(); type(t)
     139            <class 'sage.rings.function_field.maps.MapFunctionFieldToVectorSpace'>
     140        """
     141        self._V = V
     142        self._K = K
     143        self._zero = K.base_ring()(0)
     144        self._n = K.degree()
     145        FunctionFieldIsomorphism.__init__(self, Hom(K, V))
     146
     147    def domain(self):
     148        """
     149        EXAMPLES::
     150
     151            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     152            sage: V, f, t = L.vector_space()                                   
     153            sage: t.domain()
     154            Function field in Y defined by y^2 - x*y + 4*x^3
     155        """
     156        return self._K
     157
     158    def codomain(self):
     159        """
     160        EXAMPLES::
     161
     162            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     163            sage: V, f, t = L.vector_space()                                   
     164            sage: t.codomain()
     165            Vector space of dimension 2 over Rational function field in x over Rational Field       
     166        """
     167        return self._V
     168
     169    def _repr_type(self):
     170        """
     171        EXAMPLES::
     172
     173            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     174            sage: V, f, t = L.vector_space()
     175            sage: t._repr_type()
     176            'Isomorphism'
     177        """
     178        return "Isomorphism"
     179   
     180    def _call_(self, x):
     181        """
     182        EXAMPLES::
     183
     184            sage: K.<x> = FunctionField(QQ); R.<y> = K[]; L.<Y> = K.extension(y^2 - x*y + 4*x^3)
     185            sage: V, f, t = L.vector_space()                                   
     186            sage: t(x + (1/x^3)*Y)                       # indirect doctest
     187            (x, 1/x^3)
     188        """
     189        y = self._K(x)
     190        v = y.list()
     191        w = v + [self._zero]*(self._n - len(v))
     192        return self._V(w)
     193
     194
     195##########################################################################
     196# Morphisms between function fields
     197
     198class FunctionFieldMorphism(Map):
     199    """
     200    EXAMPLES::
     201
     202        sage: R.<x> = FunctionField(QQ); S.<y> = R[]
     203        sage: L.<y> = R.extension(y^2 - x^2)
     204        sage: f = L.hom(-y); f
     205        Morphism of function fields defined by y |--> -y   
     206    """
     207    def __init__(self, parent, im_gen, base_morphism):
     208        """
     209        EXAMPLES::
     210
     211            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     212            sage: L.<y> = R.extension(y^3 + 6*x^3 + x); f = L.hom(y*2); f
     213            Morphism of function fields defined by y |--> 2*y
     214            sage: type(f)
     215            <class 'sage.rings.function_field.maps.FunctionFieldMorphism'>
     216            sage: factor(L.polynomial(), proof=False)
     217            y^3 + 6*x^3 + x
     218            sage: f(y).charpoly('y')
     219            y^3 + 6*x^3 + x
     220        """
     221        self._im_gen = im_gen
     222        self._base_morphism = base_morphism
     223        Map.__init__(self, parent)
     224        # Verify that the morphism is valid:
     225        R = self.codomain()['X']
     226        v = parent.domain().polynomial().list()
     227        if base_morphism is not None:
     228            v = [base_morphism(a) for a in v]
     229        f = R(v)
     230        if f(im_gen):
     231            raise ValueError, "invalid morphism"
     232   
     233    def is_injective(self):
     234        """
     235        EXAMPLES::
     236
     237            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     238            sage: L.<y> = R.extension(y^3 + 6*x^3 + x); f = L.hom(y*2)
     239            sage: f.is_injective()
     240            True
     241        """
     242        return True
     243
     244    def __repr__(self):
     245        """
     246        EXAMPLES::
     247
     248            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     249            sage: L.<y> = R.extension(y^3 + 6*x^3 + x); f = L.hom(y*2)
     250            sage: f.__repr__()     
     251            'Morphism of function fields defined by y |--> 2*y'
     252        """
     253        return "Morphism of function fields defined by %s"%self._short_repr()
     254
     255    def __nonzero__(self):
     256        """
     257        EXAMPLES::
     258
     259            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     260            sage: L.<y> = R.extension(y^3 + 6*x^3 + x); f = L.hom(y*2)
     261            sage: f.__nonzero__()
     262            True
     263            sage: bool(f)
     264            True
     265        """
     266        return True
     267
     268    def _short_repr(self):
     269        """
     270        EXAMPLES::
     271
     272            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     273            sage: L.<y> = R.extension(y^3 + 6*x^3 + x); f = L.hom(y*2)
     274            sage: f._short_repr()
     275            'y |--> 2*y'
     276        """
     277        a = '%s |--> %s'%(self.domain().gen(), self._im_gen)
     278        if self._base_morphism is not None:
     279            a += ',  ' + self._base_morphism._short_repr()
     280        return a
     281   
     282    def _call_(self, x):
     283        """
     284        EXAMPLES::
     285
     286            sage: R.<x> = FunctionField(GF(7)); S.<y> = R[]
     287            sage: L.<y> = R.extension(y^3 + 6*x^3 + x); f = L.hom(y*2)
     288            sage: f(y/x + x^2/(x+1))            # indirect doctest
     289            2/x*y + x^2/(x + 1)
     290            sage: f(y)
     291            2*y
     292        """
     293        v = x.list()
     294        if self._base_morphism is not None:
     295            v = [self._base_morphism(a) for a in v]
     296        f = v[0].parent()['X'](v)
     297        return f(self._im_gen)
     298
     299class FunctionFieldMorphism_rational(FunctionFieldMorphism):
     300    def __init__(self, parent, im_gen):
     301        """
     302        EXAMPLES::
     303
     304            sage: R.<x> = FunctionField(GF(7)); f = R.hom(1/x); f
     305            Morphism of function fields defined by x |--> 1/x
     306            sage: type(f)
     307            <class 'sage.rings.function_field.maps.FunctionFieldMorphism_rational'>
     308        """
     309        Map.__init__(self, parent)
     310        self._im_gen = im_gen
     311        self._base_morphism = None
     312
     313    def _call_(self, x):
     314        """
     315        EXAMPLES::
     316
     317            sage: R.<x> = FunctionField(GF(7)); f = R.hom(1/x); f
     318            Morphism of function fields defined by x |--> 1/x
     319            sage: f(x+1)                          # indirect doctest
     320            (x + 1)/x
     321            sage: 1/x + 1
     322            (x + 1)/x       
     323        """
     324        a = x.element()
     325        return a.subs({a.parent().gen():self._im_gen})
  • new file sage/rings/function_field/todo.txt

    diff --git a/sage/rings/function_field/todo.txt b/sage/rings/function_field/todo.txt
    new file mode 100644
    - +  
     1TODO:
     2
     3[ ] copyright headers
     4[ ] Docstring headers for each file with description of content of file
     5[ ] picling elements
     6
     7[ ] RR space algorithm
     8
     9[ ] implement denominator in general, which is a guaranteed multiple of the denominator
     10    only when not pid...
     11[ ] reduction of divisors: algorithm
     12[ ] polynomial factoring of any univariate poly over a non-rational function field
     13[ ] checking irreducibility in FunctionField_polymod constructor
     14[ ] pickle doctests
     15[ ] TestSuite(s).run() doctests
     16[ ] method function_field() on algebraic curves, that give back a corresponding function field object.
     17[ ] compute maximal separable subfield (requested by Voloch)
     18[ ] factoring polynomials in n variables over rational function field
     19[ ] x.valuation(...)  [bradshaw will do this]
     20[ ] optimization: new implementation of the function field API, but
     21    using multivariate poly rings in some cases; for *speed*, but with
     22    less base rings supported...?
     23
     24DONE:
     25[x] phi = morphism; phi(order); phi(ideal) --- won't do, since image of order or ideal often isn't one
     26    for general morphisms
     27[x] a command FunctionField to make a new function field from anything.
     28[x] constant_base_field versus constant_field
     29[x] fix when asking for equation order if defining polynomial not *integral*
     30[x] non-monic defining polynomials
     31[x] do not require defining polynomial to be monic
     32[x] issue with *underscores* and singular:
     33K.<t_ba> = FunctionField(QQ)
     34R.<u_ba> = K[]
     35L.<u_ba> = K.extension(u_ba^2 - t_ba)
     36L.equation_order()
     37BOOM!
     38
     39[x] isomorphisms between function fields:
     40     K.hom([top gen, next one down, etc.])
     41    make sure you include easy way to gens all the way down.
     42[x] inverses of fractional ideals
     43[x] factor for elements of the rational function field
     44[x] ideals
     45[x] polynomial factoring of any univariate poly over a rational function field: reduce to bivariate over constant field?
     46[x] conversion back and forth between a free module over base
     47[x] random element
     48[x] numerator, denominator
     49[x] 100% coverage
     50[x] matrix of element
     51[x] norm
     52[x] trace
  • sage/rings/polynomial/polynomial_element.pyx

    diff --git a/sage/rings/polynomial/polynomial_element.pyx b/sage/rings/polynomial/polynomial_element.pyx
    a b  
    4848import sage.rings.finite_rings.integer_mod_ring
    4949import sage.rings.complex_field
    5050import sage.rings.fraction_field_element
     51import sage.rings.function_field
    5152import sage.rings.infinity as infinity
    5253#import sage.misc.misc as misc
    5354from sage.misc.sage_eval import sage_eval
     
    24242425                X[i] = c
    24252426        return X
    24262427
    2427     def factor(self):
     2428    def factor(self, proof=True):
    24282429        r"""
    24292430        Return the factorization of self over the base ring of this
    24302431        polynomial. Factoring polynomials over
     
    27752776        ## do better than a generic implementation, but probably not much better
    27762777        ## if there are many factors.
    27772778        ##       
     2779       
     2780
     2781        ## HUGE TODO, refactor the code below here such that this method will
     2782        ## have as only the following code
     2783        ##
     2784        ## R=self.parent().base_ring()
     2785        ## return R._factor_polynomial(self)
     2786        ##
     2787        ## in this way we can move the specific logic of factoring to the
     2788        ## self.parent().base_ring() and get rid of all the ugly
     2789        ## is_SomeType(R) checks and get way nicer structured code       
     2790        ## 200 lines of spagetti code is just way to much!
    27782791
    27792792        if self.degree() < 0:
    27802793            raise ValueError, "factorization of 0 not defined"
     
    29452958            else:
    29462959                G = self._pari_with_name('x').factor()
    29472960
     2961        elif sage.rings.function_field.function_field.is_FunctionField(R):
     2962            return R._factor_univariate_polynomial(self, proof=proof)
     2963
    29482964        #elif padic_field.is_pAdicField(R):
    29492965        #    G = list(self._pari_with_name('x').factorpadic(R.prime(), R.prec()))
    29502966           
  • sage/structure/parent.pyx

    diff --git a/sage/structure/parent.pyx b/sage/structure/parent.pyx
    a b  
    480480
    481481        - element_constructor -- A class or function that creates
    482482          elements of this Parent given appropriate input (can also be
    483           filled in later with ``_populate_coercion_lists_``
     483          filled in later with ``_populate_coercion_lists_``)
    484484
    485485        - gens -- Generators for this object (can also be filled in
    486486          later with ``_populate_generators_``)
     
    14651465           return self.Hom(codomain)(im_gens, check=check)
    14661466   
    14671467    #################################################################################
    1468     # New New Coercion support functionality
     1468    # New Coercion support functionality
    14691469    #################################################################################
    14701470   
    14711471    def _populate_coercion_lists_(self,
  • setup.py

    diff --git a/setup.py b/setup.py
    a b  
    993993
    994994                     'sage.rings',
    995995                     'sage.rings.finite_rings',
     996                     'sage.rings.function_field',
    996997                     'sage.rings.number_field',
    997998                     'sage.rings.padics',
    998999                     'sage.rings.polynomial',