Ticket #7585: 7585_3_FpT-update.patch

File 7585_3_FpT-update.patch, 58.9 KB (added by roed, 4 years ago)
  • sage/libs/flint/zmod_poly.pxd

    # HG changeset patch
    # User David Roe <roed@math.harvard.edu>
    # Date 1260892899 18000
    # Node ID 081dadd2f119edf305fae88c98e1fff8af08792e
    # Parent  1cf975c520f1a19bc9336595e86dde77b71b26f6
    Added fraction_field_FpT.pxd.  Added doctests.  Made iterators work a bit better.
    
    diff -r 1cf975c520f1 -r 081dadd2f119 sage/libs/flint/zmod_poly.pxd
    a b  
    253253    cdef unsigned long zmod_poly_evaluate(zmod_poly_t, unsigned long) 
    254254    cdef void zmod_poly_compose_horner(zmod_poly_t, zmod_poly_t, zmod_poly_t) 
    255255 
    256     # Factorization 
    257  
    258     cdef int zmod_poly_isirreducible(zmod_poly_t p) 
    259  
    260     ctypedef struct zmod_poly_factors_struct: 
    261         unsigned long num_factors 
    262         unsigned long* exponents 
    263         zmod_poly_t* factors 
    264  
    265     ctypedef zmod_poly_factors_struct* zmod_poly_factor_t 
    266  
    267     cdef void zmod_poly_factor_init(zmod_poly_factor_t) 
    268     cdef void zmod_poly_factor_clear(zmod_poly_factor_t) 
    269     cdef void zmod_poly_factor_square_free(zmod_poly_factor_t, zmod_poly_t) 
    270     cdef void zmod_poly_factor(zmod_poly_factor_t, zmod_poly_t) 
    271  
    272256    # FLINT 1.1 will have: 
    273257    # cdef void zmod_poly_powmod(zmod_poly_t res, zmod_poly_t pol, long exp, zmod_poly_t f) 
    274258 
     
    284268 
    285269    ctypedef zmod_poly_factor_struct zmod_poly_factor_t[1] 
    286270 
    287     void zmod_poly_factor_init(zmod_poly_factor_t fac) 
    288     void zmod_poly_factor_clear(zmod_poly_factor_t fac) 
     271    cdef void zmod_poly_factor_init(zmod_poly_factor_t fac) 
     272    cdef void zmod_poly_factor_clear(zmod_poly_factor_t fac) 
    289273 
    290     bint zmod_poly_isirreducible(zmod_poly_t f) 
    291     void zmod_poly_factor_add(zmod_poly_factor_t fac, zmod_poly_t poly) 
    292     void zmod_poly_factor_concat(zmod_poly_factor_t res, zmod_poly_factor_t fac) 
    293     void zmod_poly_factor_print(zmod_poly_factor_t fac) 
    294     void zmod_poly_factor_pow(zmod_poly_factor_t fac, unsigned long exp) 
     274    cdef bint zmod_poly_isirreducible(zmod_poly_t f) 
     275    cdef void zmod_poly_factor_add(zmod_poly_factor_t fac, zmod_poly_t poly) 
     276    cdef void zmod_poly_factor_concat(zmod_poly_factor_t res, zmod_poly_factor_t fac) 
     277    cdef void zmod_poly_factor_print(zmod_poly_factor_t fac) 
     278    cdef void zmod_poly_factor_pow(zmod_poly_factor_t fac, unsigned long exp) 
    295279     
    296     void zmod_poly_factor_square_free(zmod_poly_factor_t res, zmod_poly_t f) 
    297     void zmod_poly_factor_berlekamp(zmod_poly_factor_t factors, zmod_poly_t f) 
    298     unsigned long zmod_poly_factor(zmod_poly_factor_t result, zmod_poly_t input) 
     280    cdef void zmod_poly_factor_square_free(zmod_poly_factor_t res, zmod_poly_t f) 
     281    cdef void zmod_poly_factor_berlekamp(zmod_poly_factor_t factors, zmod_poly_t f) 
     282    cdef unsigned long zmod_poly_factor(zmod_poly_factor_t result, zmod_poly_t input) 
  • new file sage/rings/fraction_field_FpT.pxd

    diff -r 1cf975c520f1 -r 081dadd2f119 sage/rings/fraction_field_FpT.pxd
    - +  
     1 
     2from sage.libs.flint.zmod_poly cimport * 
     3 
     4from sage.rings.morphism cimport RingHomomorphism_coercion 
     5from sage.categories.morphism cimport Morphism 
     6from sage.structure.element cimport Element, ModuleElement, RingElement 
     7from sage.categories.map cimport Section 
     8 
     9cdef class FpTElement(RingElement): 
     10    cdef zmod_poly_t _numer, _denom 
     11    cdef bint initalized 
     12    cdef long p 
     13 
     14    cdef FpTElement _new_c(self) 
     15    cdef FpTElement _copy_c(self) 
     16    cpdef FpTElement next(self) 
     17    cpdef _sqrt_or_None(self) 
     18    cpdef bint is_square(self) 
     19 
     20cdef class FpT_iter:     
     21    cdef parent 
     22    cdef long degree 
     23    cdef FpTElement cur 
     24    cdef zmod_poly_t g 
     25     
     26cdef class Polyring_FpT_coerce(RingHomomorphism_coercion): 
     27    cdef long p 
     28cdef class FpT_Polyring_section(Section): 
     29    cdef long p 
     30cdef class Fp_FpT_coerce(RingHomomorphism_coercion): 
     31    cdef long p 
     32cdef class FpT_Fp_section(Section): 
     33    cdef long p 
     34cdef class ZZ_FpT_coerce(RingHomomorphism_coercion): 
     35    cdef long p 
     36#cdef class int_FpT_coerce(Morphism): 
     37#    cdef long p 
     38 
     39 
     40 
  • sage/rings/fraction_field_FpT.pyx

    diff -r 1cf975c520f1 -r 081dadd2f119 sage/rings/fraction_field_FpT.pyx
    a b  
     1 
     2 
    13import sys 
    24 
     5include "../ext/cdefs.pxi" 
     6include "../ext/gmp.pxi" 
     7include "../ext/interrupt.pxi" 
     8include "../ext/stdsage.pxi" 
     9 
    310from sage.rings.all import GF 
    4 from sage.rings.ring cimport Field 
    511from sage.libs.flint.zmod_poly cimport * 
    612from sage.structure.element cimport Element, ModuleElement, RingElement 
     13from sage.rings.integer_ring import ZZ 
     14from sage.rings.fraction_field import FractionField_generic 
     15from sage.rings.integer_mod cimport IntegerMod_int 
     16from sage.rings.integer cimport Integer 
     17from sage.rings.polynomial.polynomial_zmod_flint cimport Polynomial_zmod_flint 
    718import sage.algebras.algebra 
    819 
    920from sage.rings.integer_mod cimport jacobi_int, mod_inverse_int, mod_pow_int 
    1021 
    11 class Fpt(Field): 
    12     def __init__(self, long p, names='t'): 
     22class FpT(FractionField_generic): 
     23    """ 
     24    This class represents the fraction field GF(p)(T) for `2 < p < 2^16`. 
     25 
     26    EXAMPLES:: 
     27 
     28        sage: R.<T> = GF(71)[] 
     29        sage: K = FractionField(R); K 
     30        Fraction Field of Univariate Polynomial Ring in T over Finite Field of size 71 
     31        sage: TestSuite(R).run() 
     32    """ 
     33    def __init__(self, R, names=None):  # we include names so that one can use the syntax K.<t> = FpT(GF(5)['t']).  It's actually ignored 
     34        """ 
     35        INPUT: 
     36 
     37        - ``R`` -- A polynomial ring over a finite field of prime order `p` with `2 < p < 2^16` 
     38 
     39        EXAMPLES:: 
     40         
     41            sage: R.<x> = GF(31)[] 
     42            sage: K = R.fraction_field(); K 
     43            Fraction Field of Univariate Polynomial Ring in x over Finite Field of size 31 
     44        """ 
     45        cdef long p = R.base_ring().characteristic() 
    1346        assert 2 < p < 2**16 
    14         if isinstance(names, tuple): 
    15             names, = names 
    1647        self.p = p 
    17         base_ring = GF(p) 
    18         self.poly_ring = base_ring[names] 
    19         sage.algebras.algebra.Algebra.__init__(self, base_ring, names=names, normalize=True) 
    20         self._populate_coercion_lists_(element_constructor=FptElement) 
    21      
    22 #    def _element_constructor_(self, *args): 
    23 #        return FptElement(self, *args) 
    24      
    25     def ngens(self): 
    26         return 1 
    27      
    28     def gen(self, ix): 
    29         assert ix == 0 
    30         return FptElement(self, self.poly_ring.gen()) 
    31      
    32     def characteristic(self): 
    33         return self.p 
    34      
    35     def _coerce_map_from_(self, R): 
    36         return self.poly_ring.has_coerce_map_from(R) 
     48        self.poly_ring = R 
     49        FractionField_generic.__init__(self, R, element_class = FpTElement) 
     50        self._populate_coercion_lists_(coerce_list=[Polyring_FpT_coerce(self), Fp_FpT_coerce(self), ZZ_FpT_coerce(self)]) 
    3751     
    3852    def __iter__(self): 
     53        """ 
     54        Returns an iterator over this fraction field. 
     55 
     56        EXAMPLES:: 
     57 
     58            sage: R.<t> = GF(3)[]; K = R.fraction_field() 
     59            sage: iter(K) 
     60            <sage.rings.fraction_field_FpT.FpT_iter object at ...> 
     61        """ 
    3962        return self.iter() 
    4063     
    4164    def iter(self, bound=None, start=None): 
    4265        """ 
    4366            sage: from sage.rings.fraction_field_FpT import * 
    44             sage: R.<t> = Fpt(5) 
    45             sage: list(R.iter(2)) 
     67            sage: R.<t> = FpT(GF(5)['t']) 
     68            sage: list(R.iter(2))[350:355] 
     69            [(t^2 + t + 1)/(t + 2), 
     70             (t^2 + t + 2)/(t + 2), 
     71             (t^2 + t + 4)/(t + 2), 
     72             (t^2 + 2*t + 1)/(t + 2), 
     73             (t^2 + 2*t + 2)/(t + 2)] 
    4674        """ 
    47         return Fpt_iter(self, bound, start) 
     75        return FpT_iter(self, bound, start) 
    4876 
    49 cdef class FptElement(RingElement): 
     77cdef class FpTElement(RingElement): 
     78    """ 
     79    An element of an FpT fraction field. 
     80    """ 
     81     
     82    def __init__(self, parent, numer, denom=1, coerce=True, reduce=True): 
     83        """ 
     84        INPUT: 
    5085 
    51     cdef long p 
    52     cdef zmod_poly_t _numer, _denom 
    53     cdef bint initalized 
     86        - parent -- the Fraction field containing this element 
     87        - numer -- something that can be converted into the polynomial ring, giving the numerator 
     88        - denom -- something that can be converted into the polynomial ring, giving the numerator (default 1) 
    5489 
    55     def __init__(self, parent, numer, denom=1): 
    56         """ 
    5790        EXAMPLES:: 
    5891         
    5992            sage: from sage.rings.fraction_field_FpT import * 
    60             sage: R.<t> = Fpt(5) 
     93            sage: R.<t> = FpT(GF(5)['t']) 
    6194            sage: R(7) 
    6295            2 
    6396             
    6497        """ 
    6598        RingElement.__init__(self, parent) 
    66         numer = parent.poly_ring(numer) 
    67         denom = parent.poly_ring(denom) 
     99        if coerce: 
     100            numer = parent.poly_ring(numer) 
     101            denom = parent.poly_ring(denom) 
    68102        self.p = parent.p 
    69103        zmod_poly_init(self._numer, self.p) 
    70104        zmod_poly_init(self._denom, self.p) 
     
    74108            zmod_poly_set_coeff_ui(self._numer, n, a) 
    75109        for n, a in enumerate(denom): 
    76110            zmod_poly_set_coeff_ui(self._denom, n, a) 
    77         normalize(self._numer, self._denom, self.p) 
     111        if reduce: 
     112            normalize(self._numer, self._denom, self.p) 
    78113 
    79114    def __dealloc__(self): 
     115        """ 
     116        Deallocation. 
     117 
     118        EXAMPLES:: 
     119 
     120            sage: K = GF(11)['t'].fraction_field() 
     121            sage: t = K.gen() 
     122            sage: del t # indirect doctest 
     123        """ 
    80124        if self.initalized: 
    81125            zmod_poly_clear(self._numer) 
    82126            zmod_poly_clear(self._denom) 
    83127     
    84     cdef FptElement _new_c(self): 
    85         cdef FptElement x = <FptElement>PY_NEW(FptElement) 
     128    cdef FpTElement _new_c(self): 
     129        """ 
     130        Creates a new FpTElement in the same field, leaving the value to be initialized. 
     131        """ 
     132        cdef FpTElement x = <FpTElement>PY_NEW(FpTElement) 
    86133        x._parent = self._parent 
    87134        x.p = self.p 
    88135        zmod_poly_init_precomp(x._numer, x.p, self._numer.p_inv) 
     
    90137        x.initalized = True 
    91138        return x 
    92139     
    93     cdef FptElement _copy_c(self): 
    94         cdef FptElement x = <FptElement>PY_NEW(FptElement) 
     140    cdef FpTElement _copy_c(self): 
     141        """ 
     142        Creates a new FpTElement in the same field, with the same value as self. 
     143        """ 
     144        cdef FpTElement x = <FpTElement>PY_NEW(FpTElement) 
    95145        x._parent = self._parent 
    96146        x.p = self.p 
    97147        zmod_poly_init2_precomp(x._numer, x.p, self._numer.p_inv, self._numer.length) 
     
    102152        return x 
    103153     
    104154    def numer(self): 
     155        """ 
     156        Returns the numerator of this element, as an element of the polynomial ring. 
     157 
     158        EXAMPLES:: 
     159 
     160            sage: K = GF(11)['t'].fraction_field() 
     161            sage: t = K.gen(0); a = (t + 1/t)^3 - 1 
     162            sage: a.numer() 
     163            t^6 + 3*t^4 + 10*t^3 + 3*t^2 + 1 
     164        """ 
    105165        cdef long n 
    106166        return self._parent.poly_ring( 
    107167            [zmod_poly_get_coeff_ui (self._numer, n) for n in range(0, zmod_poly_degree(self._numer)+1)]) 
    108168 
     169    def numerator(self): 
     170        """ 
     171        Returns the numerator of this element, as an element of the polynomial ring. 
     172 
     173        EXAMPLES:: 
     174 
     175            sage: K = GF(11)['t'].fraction_field() 
     176            sage: t = K.gen(0); a = (t + 1/t)^3 - 1 
     177            sage: a.numerator() 
     178            t^6 + 3*t^4 + 10*t^3 + 3*t^2 + 1 
     179        """ 
     180        return self.numer() 
     181 
    109182    def denom(self): 
     183        """ 
     184        Returns the denominator of this element, as an element of the polynomial ring. 
     185 
     186        EXAMPLES:: 
     187 
     188            sage: K = GF(11)['t'].fraction_field() 
     189            sage: t = K.gen(0); a = (t + 1/t)^3 - 1 
     190            sage: a.denom() 
     191            t^3 
     192        """ 
    110193        cdef long n 
    111194        return self._parent.poly_ring( 
    112195            [zmod_poly_get_coeff_ui (self._denom, n) for n in range(0, zmod_poly_degree(self._denom)+1)]) 
    113196 
     197    def denominator(self): 
     198        """ 
     199        Returns the denominator of this element, as an element of the polynomial ring. 
     200 
     201        EXAMPLES:: 
     202 
     203            sage: K = GF(11)['t'].fraction_field() 
     204            sage: t = K.gen(0); a = (t + 1/t)^3 - 1 
     205            sage: a.denominator() 
     206            t^3 
     207        """ 
     208        return self.denom() 
     209 
    114210    def _repr_(self): 
    115211        """ 
     212        Returns a string representation of this element. 
     213         
     214        EXAMPLES:: 
     215 
    116216            sage: from sage.rings.fraction_field_FpT import * 
    117             sage: R.<t> = Fpt(17) 
    118             sage: -t 
     217            sage: R.<t> = FpT(GF(17)['t']) 
     218            sage: -t # indirect doctest 
    119219            16*t 
    120220            sage: 1/t 
    121221            1/t 
     
    138238            return "%s/%s" % (numer_s, denom_s) 
    139239     
    140240    def _latex_(self): 
     241        r""" 
     242        Returns a latex representation of this element. 
     243 
     244        EXAMPLES:: 
     245 
     246            sage: K = GF(7)['t'].fraction_field(); t = K.gen(0) 
     247            sage: latex(t^2 + 1) # indirect doctest 
     248            t^{2} + 1 
     249            sage: latex((t + 1)/(t-1)) 
     250            \frac{t + 1}{t + 6} 
     251        """ 
    141252        if zmod_poly_degree(self._denom) == 0 and zmod_poly_get_coeff_ui(self._denom, 0) == 1: 
    142253            return self.numer()._latex_() 
    143254        else: 
    144             return "{%s}/{%s}" % (self.numer()._latex_(), self.denom()._latex_()) 
    145         return  
     255            return "\\frac{%s}{%s}" % (self.numer()._latex_(), self.denom()._latex_()) 
    146256     
    147     def __cmp__(self, other): 
     257    def __richcmp__(left, right, int op): 
    148258        """ 
     259        EXAMPLES:: 
     260         
     261            sage: K = Frac(GF(5)['t']); t = K.gen() 
     262            sage: t == 1 
     263            False 
     264            sage: t + 1 < t^2 
     265            True 
     266        """ 
     267        return (<Element>left)._richcmp(right, op) 
     268 
     269    cdef int _cmp_c_impl(self, Element other) except -2: 
     270        """ 
     271        Compares this with another element. 
     272 
    149273        TESTS:: 
    150274         
    151275            sage: from sage.rings.fraction_field_FpT import * 
    152             sage: R.<t> = Fpt(7) 
     276            sage: R.<t> = FpT(GF(7)['t']) 
    153277            sage: t == t 
    154278            True 
    155279            sage: t == -t 
     
    160284            True 
    161285            sage: 1/t == 1/(t+1) 
    162286            False 
     287            sage: 2*t/t == 2 
     288            True 
     289            sage: 2*t/2 == t 
     290            True 
    163291        """ 
    164         if isinstance(other, FptElement): 
    165             # They are normalized. 
    166             if (zmod_poly_equal(self._numer, (<FptElement>other)._numer) and 
    167                     zmod_poly_equal(self._denom, (<FptElement>other)._denom)): 
    168                 return 0 
    169             else: 
    170                 return -1 
     292        # They are normalized. 
     293        if (zmod_poly_equal(self._numer, (<FpTElement>other)._numer) and 
     294            zmod_poly_equal(self._denom, (<FpTElement>other)._denom)): 
     295            return 0 
    171296        else: 
    172             return cmp(type(self), type(other)) 
     297            return -1 
    173298     
    174299    def __hash__(self): 
    175300        """ 
     301        Returns a hash value for this element. 
     302 
    176303        TESTS:: 
    177304             
    178305            sage: from sage.rings.fraction_field_FpT import * 
    179             sage: K.<t> = Fpt(7) 
     306            sage: K.<t> = FpT(GF(7)['t']) 
    180307            sage: hash(K(0)) 
    181308            0 
    182309            sage: hash(K(5)) 
    183310            5 
    184311            sage: set([1, t, 1/t, t, t, 1/t, 1+1/t, t/t]) 
    185             set([1, (t + 1)/t, t, 1/t]) 
     312            set([1/t, 1, t, (t + 1)/t]) 
    186313        """ 
    187314        if self.denom() == 1: 
    188315            return hash(self.numer()) 
    189316        return hash(str(self)) 
    190317         
    191318    def __neg__(self): 
    192         cdef FptElement x = self._new_c() 
     319        """ 
     320        Negates this element. 
     321 
     322        EXAMPLES:: 
     323 
     324            sage: K = GF(5)['t'].fraction_field(); t = K.gen(0) 
     325            sage: a = (t^2 + 2)/(t-1) 
     326            sage: -a # indirect doctest 
     327            (4*t^2 + 3)/(t + 4) 
     328        """ 
     329        cdef FpTElement x = self._new_c() 
    193330        zmod_poly_neg(x._numer, self._numer) 
    194331        zmod_poly_set(x._denom, self._denom) 
    195332        return x 
    196333         
    197334    def __invert__(self): 
     335        """ 
     336        Returns the multiplicative inverse of this element. 
     337 
     338        EXAMPLES:: 
     339 
     340            sage: K = GF(5)['t'].fraction_field(); t = K.gen(0) 
     341            sage: a = (t^2 + 2)/(t-1) 
     342            sage: ~a # indirect doctest 
     343            (t + 4)/(t^2 + 2) 
     344        """ 
    198345        if zmod_poly_degree(self._numer) == -1: 
    199346            raise ZeroDivisionError 
    200         cdef FptElement x = self._new_c() 
     347        cdef FpTElement x = self._new_c() 
    201348        zmod_poly_set(x._denom, self._numer) 
    202349        zmod_poly_set(x._numer, self._denom) 
    203350        return x 
    204351 
    205352    cpdef ModuleElement _add_(self, ModuleElement _other): 
    206353        """ 
     354        Returns the sum of this fraction field element and another. 
     355 
    207356        EXAMPLES:: 
    208357         
    209358            sage: from sage.rings.fraction_field_FpT import * 
    210             sage: R.<t> = Fpt(7) 
    211             sage: t + t 
     359            sage: R.<t> = FpT(GF(7)['t']) 
     360            sage: t + t # indirect doctest 
    212361            2*t 
    213362            sage: (t + 3) + (t + 10) 
    214363            2*t + 6 
    215364            sage: sum([t] * 7) 
    216365            0 
    217366            sage: 1/t + t 
    218             (t^2 + 1)/(t) 
     367            (t^2 + 1)/t 
    219368            sage: 1/t + 1/t^2 
    220             (t + 1)/(t^2) 
     369            (t + 1)/t^2 
    221370        """ 
    222         cdef FptElement other = <FptElement>_other 
    223         cdef FptElement x = self._new_c() 
     371        cdef FpTElement other = <FpTElement>_other 
     372        cdef FpTElement x = self._new_c() 
    224373        zmod_poly_mul(x._numer, self._numer, other._denom) 
    225374        zmod_poly_mul(x._denom, self._denom, other._numer) # use x._denom as a temp 
    226375        zmod_poly_add(x._numer, x._numer, x._denom) 
     
    230379 
    231380    cpdef ModuleElement _sub_(self, ModuleElement _other): 
    232381        """ 
     382        Returns the difference of this fraction field element and another. 
     383 
    233384        EXAMPLES:: 
    234385         
    235386            sage: from sage.rings.fraction_field_FpT import * 
    236             sage: R.<t> = Fpt(7) 
    237             sage: t - t 
     387            sage: R.<t> = FpT(GF(7)['t']) 
     388            sage: t - t # indirect doctest 
    238389            0 
    239390            sage: (t + 3) - (t + 11) 
    240             sage: 6 
     391            6 
    241392        """ 
    242         cdef FptElement other = <FptElement>_other 
    243         cdef FptElement x = self._new_c() 
     393        cdef FpTElement other = <FpTElement>_other 
     394        cdef FpTElement x = self._new_c() 
    244395        zmod_poly_mul(x._numer, self._numer, other._denom) 
    245396        zmod_poly_mul(x._denom, self._denom, other._numer) # use x._denom as a temp 
    246397        zmod_poly_sub(x._numer, x._numer, x._denom) 
     
    250401 
    251402    cpdef RingElement _mul_(self, RingElement _other): 
    252403        """ 
     404        Returns the product of this fraction field element and another. 
     405 
    253406        EXAMPLES:: 
    254407         
    255408            sage: from sage.rings.fraction_field_FpT import * 
    256             sage: R.<t> = Fpt(7) 
    257             sage: t * t 
     409            sage: R.<t> = FpT(GF(7)['t']) 
     410            sage: t * t # indirect doctest 
    258411            t^2 
    259412            sage: (t + 3) * (t + 10) 
    260413            t^2 + 6*t + 2 
    261414        """ 
    262         cdef FptElement other = <FptElement>_other 
    263         cdef FptElement x = self._new_c() 
     415        cdef FpTElement other = <FpTElement>_other 
     416        cdef FpTElement x = self._new_c() 
    264417        zmod_poly_mul(x._numer, self._numer, other._numer) 
    265418        zmod_poly_mul(x._denom, self._denom, other._denom) 
    266419        normalize(x._numer, x._denom, self.p) 
     
    268421 
    269422    cpdef RingElement _div_(self, RingElement _other): 
    270423        """ 
     424        Returns the quotient of this fraction field element and another. 
     425 
    271426        EXAMPLES:: 
    272427         
    273428            sage: from sage.rings.fraction_field_FpT import * 
    274             sage: R.<t> = Fpt(5) 
    275             sage: t / t 
     429            sage: R.<t> = FpT(GF(5)['t']) 
     430            sage: t / t # indirect doctest 
    276431            1 
    277432            sage: (t + 3) / (t + 11) 
    278433            (t + 3)/(t + 1) 
    279434            sage: (t^2 + 2*t + 1) / (t + 1) 
    280435            t + 1 
    281436        """ 
    282         cdef FptElement other = <FptElement>_other 
     437        cdef FpTElement other = <FpTElement>_other 
    283438        if zmod_poly_degree(other._numer) == -1: 
    284439            raise ZeroDivisionError 
    285         cdef FptElement x = self._new_c() 
     440        cdef FpTElement x = self._new_c() 
    286441        zmod_poly_mul(x._numer, self._numer, other._denom) 
    287442        zmod_poly_mul(x._denom, self._denom, other._numer) 
    288443        normalize(x._numer, x._denom, self.p) 
    289444        return x 
    290445     
    291     cpdef FptElement next(self): 
    292         # TODO: This misses denom > numer... 
     446    cpdef FpTElement next(self): 
    293447        """ 
     448        This function iterates through all polynomials, returning the "next" polynomial after this one. 
     449 
     450        The strategy is as follows: 
     451         
     452        - We always leave the denominator monic. 
     453 
     454        - We progress through the elements with both numerator and denominator monic, and with the denominator less than the numerator.   
     455          For each such, we output all the scalar multiples of it, then all of the scalar multiples of its inverse. 
     456 
     457        - So if the leading coefficient of the numerator is less than p-1, we scale the numerator to increase it by 1. 
     458 
     459        - Otherwise, we consider the multiple with numerator and denominator monic.   
     460         
     461          - If the numerator is less than the denominator (lexicographically), we return the inverse of that element. 
     462 
     463          - If the numerator is greater than the denominator, we invert, and then increase the numerator (remaining monic) until we either get something relatively prime to the new denominator, or we reach the new denominator.  In this case, we increase the denominator and set the numerator to 1. 
     464 
    294465        EXAMPLES:: 
    295466         
    296467            sage: from sage.rings.fraction_field_FpT import * 
    297             sage: R.<t> = Fpt(3) 
     468            sage: R.<t> = FpT(GF(3)['t']) 
    298469            sage: a = R(0) 
    299             sage: for _ in range(15): 
     470            sage: for _ in range(30): 
    300471            ...       a = a.next() 
    301472            ...       print a 
    302473            ...    
    303474            1 
    304475            2 
     476            1/t 
     477            2/t 
    305478            t 
     479            2*t 
     480            1/(t + 1) 
     481            2/(t + 1) 
    306482            t + 1 
    307             (t + 1)/(t) 
     483            2*t + 2 
     484            t/(t + 1) 
     485            2*t/(t + 1) 
     486            (t + 1)/t 
     487            (2*t + 2)/t 
     488            1/(t + 2) 
     489            2/(t + 2) 
    308490            t + 2 
    309             (t + 2)/(t) 
     491            2*t + 1 
     492            t/(t + 2) 
     493            2*t/(t + 2) 
     494            (t + 2)/t 
     495            (2*t + 1)/t 
     496            (t + 1)/(t + 2) 
     497            (2*t + 2)/(t + 2) 
    310498            (t + 2)/(t + 1) 
    311             2*t 
    312             (2*t)/(t + 1) 
    313             (2*t)/(t + 2) 
    314             2*t + 1 
    315             (2*t + 1)/(t) 
    316499            (2*t + 1)/(t + 1) 
    317             2*t + 2 
     500            1/t^2 
     501            2/t^2 
     502            t^2 
     503            2*t^2 
    318504        """ 
    319         cdef FptElement x = self._new_c() 
     505        cdef FpTElement next = self._copy_c() 
     506        cdef long a, lead 
     507        cdef zmod_poly_t g 
    320508        if zmod_poly_degree(self._numer) == -1: 
    321             zmod_poly_set_coeff_ui(x._numer, 0, 1) 
    322             zmod_poly_set_coeff_ui(x._denom, 0, 1) 
    323             return x 
    324         elif zmod_poly_degree(self._numer) == 0: 
    325             zmod_poly_set_coeff_ui(x._numer, 0, zmod_poly_get_coeff_ui(self._numer, 0) + 1) 
    326             zmod_poly_set_coeff_ui(x._denom, 0, 1) 
    327             if zmod_poly_get_coeff_ui(x._numer, 0) == 0: 
    328                 zmod_poly_set_coeff_ui(x._numer, 1, 1) 
    329             return x 
    330         cdef zmod_poly_t g 
    331         zmod_poly_init(g, self.p) 
    332         zmod_poly_set(x._numer, self._numer) 
    333         zmod_poly_set(x._denom, self._denom) 
    334         while True: 
    335             zmod_poly_inc(x._denom, True) 
    336             if zmod_poly_degree(x._numer) < zmod_poly_degree(x._denom): 
    337                 zmod_poly_inc(x._numer, False) 
    338                 zmod_poly_zero(x._denom) 
    339                 zmod_poly_set_coeff_ui(x._denom, 0, 1) 
    340             zmod_poly_gcd(g, x._numer, x._denom) 
    341             if zmod_poly_is_one(g): 
    342                 zmod_poly_clear(g) 
    343                 return x 
     509            # self should be normalized, so denom == 1 
     510            zmod_poly_set_coeff_ui(next._numer, 0, 1) 
     511            return next 
     512        lead = zmod_poly_leading(next._numer) 
     513        if lead < self.p - 1: 
     514            a = mod_inverse_int(lead, self.p) 
     515            # no overflow since self.p < 2^16 
     516            a = a * (lead + 1) % self.p 
     517            zmod_poly_scalar_mul(next._numer, next._numer, a) 
     518        else: 
     519            a = mod_inverse_int(lead, self.p) 
     520            zmod_poly_scalar_mul(next._numer, next._numer, a) 
     521            # now both next._numer and next._denom are monic.  We figure out which is lexicographically bigger: 
     522            a = zmod_poly_cmp(next._numer, next._denom) 
     523            if a == 0: 
     524                # next._numer and next._denom are relatively prime, so they're both 1. 
     525                zmod_poly_inc(next._denom, True) 
     526                return next 
     527            zmod_poly_set(next._denom, next._numer) 
     528            zmod_poly_set(next._numer, self._denom) 
     529            if a < 0: 
     530                # since next._numer is smaller, we flip and return the inverse. 
     531                return next 
     532            elif a > 0: 
     533                # since next._numer is bigger, we're in the flipped phase.  We flip back, and increment the numerator (until we reach the denominator). 
     534                zmod_poly_init(g, self.p) 
     535                try: 
     536                    while True: 
     537                        zmod_poly_inc(next._numer, True) 
     538                        if zmod_poly_equal(next._numer, next._denom): 
     539                            # Since we've reached the denominator, we reset the numerator to 1 and increment the denominator. 
     540                            zmod_poly_inc(next._denom, True) 
     541                            zmod_poly_zero(next._numer) 
     542                            zmod_poly_set_coeff_ui(next._numer, 0, 1) 
     543                            break 
     544                        else: 
     545                            # otherwise, we keep incrementing until we have a relatively prime numerator. 
     546                            zmod_poly_gcd(g, next._numer, next._denom) 
     547                            if zmod_poly_is_one(g): 
     548                                break 
     549                finally: 
     550                    zmod_poly_clear(g) 
     551        return next 
     552         
     553#         if zmod_poly_degree(self._numer) == -1: 
     554#             zmod_poly_set_coeff_ui(x._numer, 0, 1) 
     555#             zmod_poly_set_coeff_ui(x._denom, 0, 1) 
     556#             return x 
     557#         elif zmod_poly_degree(self._numer) == 0: 
     558#             zmod_poly_set_coeff_ui(x._numer, 0, zmod_poly_get_coeff_ui(self._numer, 0) + 1) 
     559#             zmod_poly_set_coeff_ui(x._denom, 0, 1) 
     560#             if zmod_poly_get_coeff_ui(x._numer, 0) == 0: 
     561#                 zmod_poly_set_coeff_ui(x._numer, 1, 1) 
     562#             return x 
     563#         cdef zmod_poly_t g 
     564#         zmod_poly_init(g, self.p) 
     565#         zmod_poly_set(x._numer, self._numer) 
     566#         zmod_poly_set(x._denom, self._denom) 
     567#         while True: 
     568#             zmod_poly_inc(x._denom, True) 
     569#             if zmod_poly_degree(x._numer) < zmod_poly_degree(x._denom): 
     570#                 zmod_poly_inc(x._numer, False) 
     571#                 zmod_poly_zero(x._denom) 
     572#                 zmod_poly_set_coeff_ui(x._denom, 0, 1) 
     573#             zmod_poly_gcd(g, x._numer, x._denom) 
     574#             if zmod_poly_is_one(g): 
     575#                 zmod_poly_clear(g) 
     576#                 return x 
    344577     
    345578    cpdef _sqrt_or_None(self): 
    346579        """ 
     
    349582        TESTS:: 
    350583         
    351584            sage: from sage.rings.fraction_field_FpT import * 
    352             sage: R.<t> = Fpt(17) 
    353             sage: sqrt(t^2) 
     585            sage: R.<t> = FpT(GF(17)['t']) 
     586            sage: sqrt(t^2) # indirect doctest 
    354587            t 
    355588            sage: sqrt(1/t^2) 
    356589            1/t 
     
    370603            sage: sqrt(t^4) 
    371604            t^2 
    372605            sage: sqrt(4*t^4/(1+t)^8) 
    373             4*t^2/(t^4 + 4*t^3 + 6*t^2 + 4*t + 1) 
     606            2*t^2/(t^4 + 4*t^3 + 6*t^2 + 4*t + 1) 
    374607             
    375             sage: R.<t> = Fpt(5) 
     608            sage: R.<t> = FpT(GF(5)['t']) 
    376609            sage: [a for a in R.iter(2) if (a^2).sqrt() not in (a,-a)] 
    377610            [] 
    378611            sage: [a for a in R.iter(2) if a.is_square() and a.sqrt()^2 != a] 
     
    385618            return None 
    386619        cdef zmod_poly_t numer 
    387620        cdef zmod_poly_t denom 
    388         cdef FptElement res 
     621        cdef FpTElement res 
    389622        try: 
    390623            zmod_poly_init(denom, self.p) 
    391624            zmod_poly_init(numer, self.p) 
     
    402635            zmod_poly_clear(denom) 
    403636     
    404637    cpdef bint is_square(self): 
     638        """ 
     639        Returns True if this element is the square of another element of the fraction field. 
     640 
     641        EXAMPLES:: 
     642 
     643            sage: K = GF(13)['t'].fraction_field(); t = K.gen() 
     644            sage: t.is_square() 
     645            False 
     646            sage: (1/t^2).is_square() 
     647            True 
     648            sage: K(0).is_square() 
     649            True 
     650        """ 
    405651        return self._sqrt_or_None() is not None 
    406652     
    407     def sqrt(self): 
     653    def sqrt(self, extend=True, all=False): 
    408654        """ 
     655        Returns the square root of this element. 
     656 
     657        INPUT: 
     658 
     659        -  ``extend`` - bool (default: True); if True, return a 
     660           square root in an extension ring, if necessary. Otherwise, raise a 
     661           ValueError if the square is not in the base ring. 
     662         
     663        -  ``all`` - bool (default: False); if True, return all 
     664           square roots of self, instead of just one. 
     665 
    409666        EXAMPLES:: 
    410667         
    411668            sage: from sage.rings.fraction_field_FpT import * 
    412             sage: R.<t> = Fpt(7) 
     669            sage: K = GF(7)['t'].fraction_field(); t = K.gen(0) 
     670            sage: ((t + 2)^2/(3*t^3 + 1)^4).sqrt() 
     671            (3*t + 6)/(t^6 + 3*t^3 + 4) 
    413672        """ 
    414673        s = self._sqrt_or_None() 
    415674        if s is None: 
    416             raise ValueError, "not a perfect square" 
     675            if extend: 
     676                raise NotImplementedError, "function fields not yet implemented" 
     677            else: 
     678                raise ValueError, "not a perfect square" 
    417679        else: 
    418             return s 
     680            if all: 
     681                if not s: 
     682                    return [s] 
     683                else: 
     684                    return [s, -s] 
     685            else: 
     686                return s 
    419687     
    420     def __pow__(FptElement self, Py_ssize_t e, dummy): 
     688    def __pow__(FpTElement self, Py_ssize_t e, dummy): 
    421689        """ 
     690        Returns the ``e``th power of this element. 
     691 
    422692        EXAMPLES:: 
    423693         
    424694            sage: from sage.rings.fraction_field_FpT import * 
    425             sage: R.<t> = Fpt(7) 
     695            sage: R.<t> = FpT(GF(7)['t']) 
    426696            sage: t^5 
    427697            t^5 
    428698            sage: t^-5 
     
    446716        """ 
    447717        cdef long a 
    448718        assert dummy is None 
    449         cdef FptElement x = self._new_c() 
     719        cdef FpTElement x = self._new_c() 
    450720        if e >= 0: 
    451721            zmod_poly_pow(x._numer, self._numer, e) 
    452722            zmod_poly_pow(x._denom, self._denom, e) 
     
    460730        return x 
    461731 
    462732         
    463 cdef class Fpt_iter: 
    464      
    465     cdef parent 
    466     cdef long degree 
    467     cdef FptElement cur 
    468     cdef zmod_poly_t g 
    469      
    470     def __init__(self, parent, degree=None, FptElement start=None): 
    471         if degree is None: 
    472             raise NotImplementedError 
     733cdef class FpT_iter: 
     734    """ 
     735    Returns a class that iterates over all elements of an FpT. 
     736 
     737    EXAMPLES:: 
     738 
     739        sage: K = GF(3)['t'].fraction_field() 
     740        sage: I = K.iter(1) 
     741        sage: list(I) 
     742        [0, 
     743         1, 
     744         2, 
     745         t, 
     746         t + 1, 
     747         t + 2, 
     748         2*t, 
     749         2*t + 1, 
     750         2*t + 2, 
     751         1/t, 
     752         2/t, 
     753         (t + 1)/t, 
     754         (t + 2)/t, 
     755         (2*t + 1)/t, 
     756         (2*t + 2)/t, 
     757         1/(t + 1), 
     758         2/(t + 1), 
     759         t/(t + 1), 
     760         (t + 2)/(t + 1), 
     761         2*t/(t + 1), 
     762         (2*t + 1)/(t + 1), 
     763         1/(t + 2), 
     764         2/(t + 2), 
     765         t/(t + 2), 
     766         (t + 1)/(t + 2), 
     767         2*t/(t + 2), 
     768         (2*t + 2)/(t + 2)] 
     769    """ 
     770    def __init__(self, parent, degree=None, FpTElement start=None): 
     771        """ 
     772        INPUTS: 
     773         
     774        - parent -- The FpT that we're iterating over. 
     775 
     776        - degree -- The maximum degree of the numerator and denominator of the elements over which we iterate. 
     777         
     778        - start -- (default 0) The element on which to start. 
     779 
     780        EXAMPLES:: 
     781 
     782            sage: K = GF(11)['t'].fraction_field() 
     783            sage: I = K.iter(2) # indirect doctest 
     784            sage: for a in I: 
     785            ...       if a.denom()[0] == 3 and a.numer()[1] == 2: 
     786            ...           print a; break 
     787            2*t/(t + 3) 
     788        """ 
     789        #if degree is None: 
     790        #    raise NotImplementedError 
    473791        self.parent = parent 
    474792        self.cur = start 
    475         self.degree = sys.maxint if degree is None else degree 
     793        self.degree = -2 if degree is None else degree 
    476794     
    477795    def __cinit__(self, parent, *args, **kwds): 
     796        """ 
     797        Memory allocation for the temp variable storing the gcd of the numerator and denominator. 
     798 
     799        TESTS:: 
     800 
     801            sage: from sage.rings.fraction_field_FpT import FpT_iter 
     802            sage: K = GF(7)['t'].fraction_field() 
     803            sage: I = FpT_iter(K, 3) # indirect doctest 
     804            sage: I 
     805            <sage.rings.fraction_field_FpT.FpT_iter object at ...> 
     806        """ 
    478807        zmod_poly_init(self.g, parent.characteristic()) 
    479808     
    480809    def __dealloc__(self): 
     810        """ 
     811        Deallocating of the self.g 
     812 
     813        TESTS:: 
     814 
     815            sage: from sage.rings.fraction_field_FpT import FpT_iter 
     816            sage: K = GF(7)['t'].fraction_field() 
     817            sage: I = FpT_iter(K, 3) 
     818            sage: del I # indirect doctest 
     819        """ 
    481820        zmod_poly_clear(self.g) 
    482821     
    483822    def __iter__(self): 
     823        """ 
     824        Returns this iterator. 
     825 
     826        TESTS:: 
     827 
     828            sage: from sage.rings.fraction_field_FpT import FpT_iter 
     829            sage: K = GF(3)['t'].fraction_field() 
     830            sage: I = FpT_iter(K, 3) 
     831            sage: for a in I: # indirect doctest 
     832            ...       if a.numer()[1] == 1 and a.denom()[1] == 2 and a.is_square(): 
     833            ...            print a; break 
     834            (t^2 + t + 1)/(t^2 + 2*t + 1) 
     835        """ 
    484836        return self 
    485837     
    486838    def __next__(self): 
    487839        """ 
     840        Returns the next element to iterate over. 
     841 
     842        This is achieved by iterating over monic denominators, and for each denominator,  
     843        iterating over all numerators relatively prime to the given denominator.  
     844 
    488845        EXAMPLES:: 
    489846         
    490847            sage: from sage.rings.fraction_field_FpT import * 
    491             sage: K.<t> = Fpt(3) 
    492             sage: list(K.iter(1)) 
     848            sage: K.<t> = FpT(GF(3)['t']) 
     849            sage: list(K.iter(1)) # indirect doctest 
    493850            [0, 
    494851             1, 
    495852             2, 
     
    521878            sage: len(list(K.iter(3))) 
    522879            2187 
    523880 
    524             sage: K.<t> = Fpt(5) 
    525             sage: L = list(K.iter(3)) 
     881            sage: K.<t> = FpT(GF(5)['t']) 
     882            sage: L = list(K.iter(3)); len(L) 
    526883            78125 
    527884            sage: L[:10] 
    528885            [0, 1, 2, 3, 4, t, t + 1, t + 2, t + 3, t + 4] 
     
    531888            sage: L[-1] 
    532889            (4*t^3 + 4*t^2 + 4*t + 4)/(t^3 + 4*t^2 + 4*t + 4) 
    533890        """ 
    534         cdef FptElement next 
     891        cdef FpTElement next 
    535892        if self.cur is None: 
    536893            self.cur = self.parent(0) 
     894        elif self.degree == -2: 
     895            self.cur = self.cur.next() 
    537896        else: 
    538897            next = self.cur._copy_c() 
     898            _sig_on 
    539899            while True: 
    540900                zmod_poly_inc(next._numer, False) 
    541901                if zmod_poly_degree(next._numer) > self.degree: 
     
    547907                zmod_poly_gcd(self.g, next._numer, next._denom) 
    548908                if zmod_poly_is_one(self.g): 
    549909                    break 
     910            _sig_off 
    550911            self.cur = next 
    551912#            self.cur = self.cur.next() 
    552913#            if zmod_poly_degree(self.cur._numer) > self.degree: 
    553914#                raise StopIteration 
    554915        return self.cur 
    555916 
     917cdef class Polyring_FpT_coerce(RingHomomorphism_coercion): 
     918    """ 
     919    This class represents the coercion map from GF(p)[t] to GF(p)(t) 
    556920 
     921    EXAMPLES:: 
     922 
     923        sage: R.<t> = GF(5)[] 
     924        sage: K = R.fraction_field() 
     925        sage: f = K.coerce_map_from(R); f 
     926        Ring Coercion morphism: 
     927          From: Univariate Polynomial Ring in t over Finite Field of size 5 
     928          To:   Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 
     929        sage: type(f) 
     930        <type 'sage.rings.fraction_field_FpT.Polyring_FpT_coerce'> 
     931    """ 
     932    def __init__(self, R): 
     933        """ 
     934        INPUTS: 
     935         
     936        - R -- An FpT 
     937 
     938        EXAMPLES:: 
     939 
     940            sage: R.<t> = GF(next_prime(2000))[] 
     941            sage: K = R.fraction_field() # indirect doctest 
     942        """ 
     943        RingHomomorphism_coercion.__init__(self, R.ring_of_integers().Hom(R), check=False) 
     944        self.p = R.base_ring().characteristic() 
     945         
     946    cpdef Element _call_(self, _x): 
     947        """ 
     948        Applies the coercion. 
     949 
     950        EXAMPLES:: 
     951 
     952            sage: R.<t> = GF(5)[] 
     953            sage: K = R.fraction_field() 
     954            sage: f = K.coerce_map_from(R) 
     955            sage: f(t^2 + 1) # indirect doctest 
     956            t^2 + 1 
     957        """ 
     958        cdef Polynomial_zmod_flint x = <Polynomial_zmod_flint?> _x 
     959        cdef FpTElement ans = <FpTElement>PY_NEW(FpTElement) 
     960        ans._parent = self._codomain 
     961        ans.p = self.p 
     962        zmod_poly_init(ans._numer, ans.p) 
     963        zmod_poly_init(ans._denom, ans.p) 
     964        zmod_poly_set(ans._numer, &x.x) 
     965        zmod_poly_set_coeff_ui(ans._denom, 0, 1) 
     966        ans.initalized = True 
     967        return ans 
     968 
     969    cpdef Element _call_with_args(self, _x, args=(), kwds={}): 
     970        """ 
     971        This function allows the map to take multiple arguments, usually used to specify both numerator and denominator. 
     972 
     973        If ``reduce`` is specified as False, then the result won't be normalized. 
     974 
     975        EXAMPLES:: 
     976 
     977            sage: R.<t> = GF(5)[] 
     978            sage: K = R.fraction_field() 
     979            sage: f = K.coerce_map_from(R) 
     980            sage: f(2*t + 2, t + 3) # indirect doctest 
     981            (2*t + 2)/(t + 3) 
     982            sage: f(2*t + 2, 2) 
     983            t + 1 
     984            sage: f(2*t + 2, 2, reduce=False) 
     985            (2*t + 2)/2 
     986        """ 
     987        cdef Polynomial_zmod_flint x = <Polynomial_zmod_flint?> _x 
     988        cdef FpTElement ans = <FpTElement>PY_NEW(FpTElement) 
     989        ans._parent = self._codomain 
     990        ans.p = self.p 
     991        zmod_poly_init(ans._numer, ans.p) 
     992        zmod_poly_init(ans._denom, ans.p) 
     993        cdef long r 
     994        zmod_poly_set(ans._numer, &x.x) 
     995        if len(args) == 0: 
     996            zmod_poly_set_coeff_ui(ans._denom, 0, 1) 
     997        elif len(args) == 1: 
     998            y = args[0] 
     999            if PY_TYPE_CHECK(y, Integer): 
     1000                r = mpz_fdiv_ui((<Integer>y).value, self.p) 
     1001                if r == 0: 
     1002                    raise ZeroDivisionError 
     1003                zmod_poly_set_coeff_ui(ans._denom, 0, r) 
     1004            else: 
     1005                # could use the coerce keyword being set to False to not check this... 
     1006                if not (PY_TYPE_CHECK(y, Element) and y.parent() is self._domain): 
     1007                    # We could special case integers and GF(p) elements here. 
     1008                    y = self._domain(y) 
     1009                zmod_poly_set(ans._denom, &((<Polynomial_zmod_flint?>y).x)) 
     1010        else: 
     1011            raise ValueError, "FpT only supports two positional arguments" 
     1012        if not (kwds.has_key('reduce') and not kwds['reduce']): 
     1013            normalize(ans._numer, ans._denom, ans.p) 
     1014        ans.initalized = True 
     1015        return ans 
     1016 
     1017    def section(self): 
     1018        """ 
     1019        Returns the section of this inclusion: the partially defined map from ``GF(p)(t)``  
     1020        back to ``GF(p)[t]``, defined on elements with unit denominator. 
     1021 
     1022        EXAMPLES:: 
     1023 
     1024            sage: R.<t> = GF(5)[] 
     1025            sage: K = R.fraction_field() 
     1026            sage: f = K.coerce_map_from(R) 
     1027            sage: g = f.section(); g 
     1028            Section map: 
     1029              From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 
     1030              To:   Univariate Polynomial Ring in t over Finite Field of size 5 
     1031            sage: t = K.gen() 
     1032            sage: g(t) 
     1033            t 
     1034            sage: g(1/t) 
     1035            Traceback (most recent call last): 
     1036            ... 
     1037            ValueError: not integral 
     1038        """ 
     1039        return FpT_Polyring_section(self) 
     1040 
     1041cdef class FpT_Polyring_section(Section): 
     1042    """ 
     1043    This class represents the section from GF(p)(t) back to GF(p)[t] 
     1044 
     1045    EXAMPLES:: 
     1046 
     1047        sage: R.<t> = GF(5)[] 
     1048        sage: K = R.fraction_field() 
     1049        sage: f = R.convert_map_from(K); f 
     1050        Section map: 
     1051          From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 
     1052          To:   Univariate Polynomial Ring in t over Finite Field of size 5 
     1053        sage: type(f) 
     1054        <type 'sage.rings.fraction_field_FpT.FpT_Polyring_section'> 
     1055    """ 
     1056    def __init__(self, Polyring_FpT_coerce f): 
     1057        """ 
     1058        INPUTS: 
     1059         
     1060        - f -- A Polyring_FpT_coerce homomorphism 
     1061 
     1062        EXAMPLES:: 
     1063 
     1064            sage: R.<t> = GF(next_prime(2000))[] 
     1065            sage: K = R.fraction_field() 
     1066            sage: R(K.gen(0)) # indirect doctest 
     1067            t 
     1068        """ 
     1069        self.p = f.p 
     1070        Section.__init__(self, f) 
     1071     
     1072    cpdef Element _call_(self, _x): 
     1073        """ 
     1074        Applies the section. 
     1075 
     1076        EXAMPLES:: 
     1077 
     1078            sage: R.<t> = GF(7)[] 
     1079            sage: K = R.fraction_field() 
     1080            sage: f = K.coerce_map_from(R) 
     1081            sage: g = f.section(); g 
     1082            Section map: 
     1083              From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 
     1084              To:   Univariate Polynomial Ring in t over Finite Field of size 7 
     1085            sage: t = K.gen() 
     1086            sage: g(t^2) # indirect doctest 
     1087            t^2 
     1088            sage: g(1/t) 
     1089            Traceback (most recent call last): 
     1090            ... 
     1091            ValueError: not integral 
     1092        """ 
     1093        cdef FpTElement x = <FpTElement?>_x 
     1094        cdef Polynomial_zmod_flint ans 
     1095        if zmod_poly_degree(x._denom) != 0: 
     1096            normalize(x._numer, x._denom, self.p) 
     1097            if zmod_poly_degree(x._denom) != 0: 
     1098                raise ValueError, "not integral" 
     1099        ans = PY_NEW(Polynomial_zmod_flint) 
     1100        if zmod_poly_get_coeff_ui(x._denom, 0) != 1: 
     1101            normalize(x._numer, x._denom, self.p) 
     1102        zmod_poly_init(&ans.x, self.p) 
     1103        zmod_poly_set(&ans.x, x._numer) 
     1104        ans._parent = self._codomain 
     1105        return ans 
     1106 
     1107cdef class Fp_FpT_coerce(RingHomomorphism_coercion): 
     1108    """ 
     1109    This class represents the coercion map from GF(p) to GF(p)(t) 
     1110 
     1111    EXAMPLES:: 
     1112 
     1113        sage: R.<t> = GF(5)[] 
     1114        sage: K = R.fraction_field() 
     1115        sage: f = K.coerce_map_from(GF(5)); f 
     1116        Ring Coercion morphism: 
     1117          From: Finite Field of size 5 
     1118          To:   Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 
     1119        sage: type(f) 
     1120        <type 'sage.rings.fraction_field_FpT.Fp_FpT_coerce'> 
     1121    """ 
     1122    def __init__(self, R): 
     1123        """ 
     1124        INPUTS: 
     1125         
     1126        - R -- An FpT 
     1127 
     1128        EXAMPLES:: 
     1129 
     1130            sage: R.<t> = GF(next_prime(3000))[] 
     1131            sage: K = R.fraction_field() # indirect doctest 
     1132        """ 
     1133        RingHomomorphism_coercion.__init__(self, R.base_ring().Hom(R), check=False) 
     1134        self.p = R.base_ring().characteristic() 
     1135         
     1136    cpdef Element _call_(self, _x): 
     1137        """ 
     1138        Applies the coercion. 
     1139 
     1140        EXAMPLES:: 
     1141 
     1142            sage: R.<t> = GF(5)[] 
     1143            sage: K = R.fraction_field() 
     1144            sage: f = K.coerce_map_from(GF(5)) 
     1145            sage: f(GF(5)(3)) # indirect doctest 
     1146            3 
     1147        """ 
     1148        cdef IntegerMod_int x = <IntegerMod_int?> _x 
     1149        cdef FpTElement ans = <FpTElement>PY_NEW(FpTElement) 
     1150        ans._parent = self._codomain 
     1151        ans.p = self.p 
     1152        zmod_poly_init(ans._numer, ans.p) 
     1153        zmod_poly_init(ans._denom, ans.p) 
     1154        zmod_poly_set_coeff_ui(ans._numer, 0, x.ivalue) 
     1155        zmod_poly_set_coeff_ui(ans._denom, 0, 1) 
     1156        ans.initalized = True 
     1157        return ans 
     1158 
     1159    cpdef Element _call_with_args(self, _x, args=(), kwds={}): 
     1160        """ 
     1161        This function allows the map to take multiple arguments, usually used to specify both numerator and denominator. 
     1162 
     1163        If ``reduce`` is specified as False, then the result won't be normalized. 
     1164 
     1165        EXAMPLES:: 
     1166 
     1167            sage: R.<t> = GF(5)[] 
     1168            sage: K = R.fraction_field() 
     1169            sage: f = K.coerce_map_from(GF(5)) 
     1170            sage: f(1, t + 3) # indirect doctest 
     1171            1/(t + 3) 
     1172            sage: f(2, 2*t) 
     1173            1/t 
     1174            sage: f(2, 2*t, reduce=False) 
     1175            2/2*t 
     1176        """ 
     1177        cdef IntegerMod_int x = <IntegerMod_int?> _x 
     1178        cdef FpTElement ans = <FpTElement>PY_NEW(FpTElement) 
     1179        ans._parent = self._codomain 
     1180        ans.p = self.p 
     1181        zmod_poly_init(ans._numer, ans.p) 
     1182        zmod_poly_init(ans._denom, ans.p) 
     1183        cdef long r 
     1184        zmod_poly_set_coeff_ui(ans._numer, 0, x.ivalue) 
     1185        if len(args) == 0: 
     1186            zmod_poly_set_coeff_ui(ans._denom, 0, 1) 
     1187        if len(args) == 1: 
     1188            y = args[0] 
     1189            if PY_TYPE_CHECK(y, Integer): 
     1190                r = mpz_fdiv_ui((<Integer>y).value, self.p) 
     1191                if r == 0: 
     1192                    raise ZeroDivisionError 
     1193                zmod_poly_set_coeff_ui(ans._denom, 0, r) 
     1194            else: 
     1195                R = self._codomain.ring_of_integers() 
     1196                # could use the coerce keyword being set to False to not check this... 
     1197                if not (PY_TYPE_CHECK(y, Element) and y.parent() is R): 
     1198                    # We could special case integers and GF(p) elements here. 
     1199                    y = R(y) 
     1200                zmod_poly_set(ans._denom, &((<Polynomial_zmod_flint?>y).x)) 
     1201        else: 
     1202            raise ValueError, "FpT only supports two positional arguments" 
     1203        if not (kwds.has_key('reduce') and not kwds['reduce']): 
     1204            normalize(ans._numer, ans._denom, ans.p) 
     1205        ans.initalized = True 
     1206        return ans 
     1207 
     1208    def section(self): 
     1209        """ 
     1210        Returns the section of this inclusion: the partially defined map from ``GF(p)(t)``  
     1211        back to ``GF(p)``, defined on constant elements. 
     1212 
     1213        EXAMPLES:: 
     1214 
     1215            sage: R.<t> = GF(5)[] 
     1216            sage: K = R.fraction_field() 
     1217            sage: f = K.coerce_map_from(GF(5)) 
     1218            sage: g = f.section(); g 
     1219            Section map: 
     1220              From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 
     1221              To:   Finite Field of size 5 
     1222            sage: t = K.gen() 
     1223            sage: g(f(1,3,reduce=False)) 
     1224            2 
     1225            sage: g(t) 
     1226            Traceback (most recent call last): 
     1227            ... 
     1228            ValueError: not constant             
     1229            sage: g(1/t) 
     1230            Traceback (most recent call last): 
     1231            ... 
     1232            ValueError: not integral 
     1233        """ 
     1234        return FpT_Fp_section(self) 
     1235 
     1236cdef class FpT_Fp_section(Section): 
     1237    """ 
     1238    This class represents the section from GF(p)(t) back to GF(p)[t] 
     1239 
     1240    EXAMPLES:: 
     1241 
     1242        sage: R.<t> = GF(5)[] 
     1243        sage: K = R.fraction_field() 
     1244        sage: f = GF(5).convert_map_from(K); f 
     1245        Section map: 
     1246          From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 
     1247          To:   Finite Field of size 5 
     1248        sage: type(f) 
     1249        <type 'sage.rings.fraction_field_FpT.FpT_Fp_section'> 
     1250    """ 
     1251    def __init__(self, Fp_FpT_coerce f): 
     1252        """ 
     1253        INPUTS: 
     1254         
     1255        - f -- An Fp_FpT_coerce homomorphism 
     1256 
     1257        EXAMPLES:: 
     1258 
     1259            sage: R.<t> = GF(next_prime(2000))[] 
     1260            sage: K = R.fraction_field() 
     1261            sage: GF(next_prime(2000))(K(127)) # indirect doctest 
     1262            127 
     1263        """ 
     1264        self.p = f.p 
     1265        Section.__init__(self, f) 
     1266     
     1267    cpdef Element _call_(self, _x): 
     1268        """ 
     1269        Applies the section. 
     1270 
     1271        EXAMPLES:: 
     1272 
     1273            sage: R.<t> = GF(7)[] 
     1274            sage: K = R.fraction_field() 
     1275            sage: f = K.coerce_map_from(GF(7)) 
     1276            sage: g = f.section(); g 
     1277            Section map: 
     1278              From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 
     1279              To:   Finite Field of size 7 
     1280            sage: t = K.gen() 
     1281            sage: g(t^2) # indirect doctest 
     1282            Traceback (most recent call last): 
     1283            ... 
     1284            ValueError: not constant 
     1285            sage: g(1/t) 
     1286            Traceback (most recent call last): 
     1287            ... 
     1288            ValueError: not integral 
     1289            sage: g(K(4)) 
     1290            4 
     1291            sage: g(K(0)) 
     1292            0 
     1293        """ 
     1294        cdef FpTElement x = <FpTElement?>_x 
     1295        cdef IntegerMod_int ans 
     1296        if zmod_poly_degree(x._denom) != 0 or zmod_poly_degree(x._numer) > 0: 
     1297            normalize(x._numer, x._denom, self.p) 
     1298            if zmod_poly_degree(x._denom) != 0: 
     1299                raise ValueError, "not integral" 
     1300            if zmod_poly_degree(x._numer) > 0: 
     1301                raise ValueError, "not constant" 
     1302        ans = PY_NEW(IntegerMod_int) 
     1303        ans.__modulus = self._codomain._pyx_order 
     1304        if zmod_poly_get_coeff_ui(x._denom, 0) != 1: 
     1305            normalize(x._numer, x._denom, self.p) 
     1306        ans.ivalue = zmod_poly_get_coeff_ui(x._numer, 0) 
     1307        ans._parent = self._codomain 
     1308        return ans 
     1309 
     1310cdef class ZZ_FpT_coerce(RingHomomorphism_coercion): 
     1311    """ 
     1312    This class represents the coercion map from ZZ to GF(p)(t) 
     1313 
     1314    EXAMPLES:: 
     1315 
     1316        sage: R.<t> = GF(17)[] 
     1317        sage: K = R.fraction_field() 
     1318        sage: f = K.coerce_map_from(ZZ); f 
     1319        Ring Coercion morphism: 
     1320          From: Integer Ring 
     1321          To:   Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 17 
     1322        sage: type(f) 
     1323        <type 'sage.rings.fraction_field_FpT.ZZ_FpT_coerce'> 
     1324    """ 
     1325    def __init__(self, R): 
     1326        """ 
     1327        INPUTS: 
     1328         
     1329        - R -- An FpT 
     1330 
     1331        EXAMPLES:: 
     1332 
     1333            sage: R.<t> = GF(next_prime(3000))[] 
     1334            sage: K = R.fraction_field() # indirect doctest 
     1335        """ 
     1336        RingHomomorphism_coercion.__init__(self, ZZ.Hom(R), check=False) 
     1337        self.p = R.base_ring().characteristic() 
     1338         
     1339    cpdef Element _call_(self, _x): 
     1340        """ 
     1341        Applies the coercion. 
     1342 
     1343        EXAMPLES:: 
     1344 
     1345            sage: R.<t> = GF(5)[] 
     1346            sage: K = R.fraction_field() 
     1347            sage: f = K.coerce_map_from(ZZ) 
     1348            sage: f(3) # indirect doctest 
     1349            3 
     1350        """ 
     1351        cdef Integer x = <Integer?> _x 
     1352        cdef FpTElement ans = <FpTElement>PY_NEW(FpTElement) 
     1353        ans._parent = self._codomain 
     1354        ans.p = self.p 
     1355        zmod_poly_init(ans._numer, ans.p) 
     1356        zmod_poly_init(ans._denom, ans.p) 
     1357        zmod_poly_set_coeff_ui(ans._numer, 0, mpz_fdiv_ui(x.value, self.p)) 
     1358        zmod_poly_set_coeff_ui(ans._denom, 0, 1) 
     1359        ans.initalized = True 
     1360        return ans 
     1361 
     1362    cpdef Element _call_with_args(self, _x, args=(), kwds={}): 
     1363        """ 
     1364        This function allows the map to take multiple arguments, usually used to specify both numerator and denominator. 
     1365 
     1366        If ``reduce`` is specified as False, then the result won't be normalized. 
     1367 
     1368        EXAMPLES:: 
     1369 
     1370            sage: R.<t> = GF(5)[] 
     1371            sage: K = R.fraction_field() 
     1372            sage: f = K.coerce_map_from(ZZ) 
     1373            sage: f(1, t + 3) # indirect doctest 
     1374            1/(t + 3) 
     1375            sage: f(1,2) 
     1376            3 
     1377            sage: f(2, 2*t) 
     1378            1/t 
     1379            sage: f(2, 2*t, reduce=False) 
     1380            2/2*t 
     1381        """ 
     1382        cdef Integer x = <Integer?> _x 
     1383        cdef FpTElement ans = <FpTElement>PY_NEW(FpTElement) 
     1384        ans._parent = self._codomain 
     1385        ans.p = self.p 
     1386        zmod_poly_init(ans._numer, ans.p) 
     1387        zmod_poly_init(ans._denom, ans.p) 
     1388        cdef long r 
     1389        zmod_poly_set_coeff_ui(ans._numer, 0, mpz_fdiv_ui(x.value, self.p)) 
     1390        if len(args) == 0: 
     1391            zmod_poly_set_coeff_ui(ans._denom, 0, 1) 
     1392        if len(args) == 1: 
     1393            y = args[0] 
     1394            if PY_TYPE_CHECK(y, Integer): 
     1395                r = mpz_fdiv_ui((<Integer>y).value, self.p) 
     1396                if r == 0: 
     1397                    raise ZeroDivisionError 
     1398                zmod_poly_set_coeff_ui(ans._denom, 0, r) 
     1399            else: 
     1400                R = self._codomain.ring_of_integers() 
     1401                # could use the coerce keyword being set to False to not check this... 
     1402                if not (PY_TYPE_CHECK(y, Element) and y.parent() is R): 
     1403                    # We could special case integers and GF(p) elements here. 
     1404                    y = R(y) 
     1405                zmod_poly_set(ans._denom, &((<Polynomial_zmod_flint?>y).x)) 
     1406        else: 
     1407            raise ValueError, "FpT only supports two positional arguments" 
     1408        if not (kwds.has_key('reduce') and not kwds['reduce']): 
     1409            normalize(ans._numer, ans._denom, ans.p) 
     1410        ans.initalized = True 
     1411        return ans 
     1412 
     1413    def section(self): 
     1414        """ 
     1415        Returns the section of this inclusion: the partially defined map from ``GF(p)(t)``  
     1416        back to ``ZZ``, defined on constant elements. 
     1417 
     1418        EXAMPLES:: 
     1419 
     1420            sage: R.<t> = GF(5)[] 
     1421            sage: K = R.fraction_field() 
     1422            sage: f = K.coerce_map_from(ZZ) 
     1423            sage: g = f.section(); g 
     1424            Composite map: 
     1425              From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 
     1426              To:   Integer Ring 
     1427              Defn:   Section map: 
     1428                      From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 
     1429                      To:   Finite Field of size 5 
     1430                    then 
     1431                      Lifting morphism: 
     1432                      From: Finite Field of size 5 
     1433                      To:   Integer Ring 
     1434            sage: t = K.gen() 
     1435            sage: g(f(1,3,reduce=False)) 
     1436            2 
     1437            sage: g(t) 
     1438            Traceback (most recent call last): 
     1439            ... 
     1440            ValueError: not constant             
     1441            sage: g(1/t) 
     1442            Traceback (most recent call last): 
     1443            ... 
     1444            ValueError: not integral 
     1445        """ 
     1446        return self._codomain.base_ring().coerce_map_from(ZZ).section() * Fp_FpT_coerce(self._codomain).section() 
     1447 
     1448# cdef class int_FpT_coerce(Morphism): 
     1449#     """ 
     1450#     This class represents the coercion map from int to GF(p)(t) 
     1451 
     1452#     EXAMPLES:: 
     1453 
     1454#         sage: R.<t> = GF(17)[] 
     1455#         sage: K = R.fraction_field() 
     1456#         sage: f = K.coerce_map_from(int); f 
     1457#         Ring Coercion morphism: 
     1458#           From: Integer Ring 
     1459#           To:   Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 17 
     1460#         sage: type(f) 
     1461#         <type 'sage.rings.fraction_field_FpT.ZZ_FpT_coerce'> 
     1462#     """ 
     1463#     def __init__(self, R): 
     1464#         import sage.categories.homset 
     1465#         from sage.structure.parent import Set_PythonType 
     1466#         Morphism.__init__(self, sage.categories.homset.Hom(Set_PythonType(int), R)) 
     1467#         self.p = R.base_ring().characteristic() 
     1468 
     1469#     cpdef Element _call_(self, a): 
     1470#         cdef FpTElement ans = <FpTElement>PY_NEW(FpTElement) 
     1471#         ans._parent = self._codomain 
     1472#         ans.p = self.p 
     1473#         zmod_poly_init(ans._numer, ans.p) 
     1474#         zmod_poly_init(ans._denom, ans.p) 
     1475#         cdef long amodp = PyInt_AS_LONG(a) % self.p 
     1476#         if amodp < 0: 
     1477#             amodp = self.p - amodp 
     1478#         zmod_poly_set_coeff_ui(ans._numer, 0, amodp) 
     1479#         zmod_poly_set_coeff_ui(ans._denom, 0, 1) 
     1480#         ans.initalized = True 
     1481#         return ans 
     1482 
     1483#     def _repr_type(self): 
     1484#         return "Native"   
    5571485 
    5581486cdef inline bint normalize(zmod_poly_t numer, zmod_poly_t denom, long p): 
     1487    """ 
     1488    Puts numer/denom into a normal form: denominator monic and sharing no common factor with the numerator. 
     1489 
     1490    The normalized form of 0 is 0/1. 
     1491 
     1492    Returns True if numer and denom were changed. 
     1493    """ 
    5591494    cdef long a 
     1495    cdef bint changed 
    5601496    if zmod_poly_degree(numer) == -1: 
     1497        if zmod_poly_degree(denom) > 0 or zmod_poly_leading(denom) != 1: 
     1498            changed = True 
     1499        else: 
     1500            changed = False 
    5611501        zmod_poly_truncate(denom, 0) 
    5621502        zmod_poly_set_coeff_ui(denom, 0, 1) 
     1503        return changed 
    5631504    elif zmod_poly_degree(numer) == 0 or zmod_poly_degree(denom) == 0: 
    5641505        if zmod_poly_leading(denom) != 1: 
    5651506            a = mod_inverse_int(zmod_poly_leading(denom), p) 
     
    5681509            return True 
    5691510        return False 
    5701511    cdef zmod_poly_t g 
    571     cdef bint changed = False 
     1512    changed = False 
    5721513    try: 
    5731514        zmod_poly_init_precomp(g, p, numer.p_inv) 
    5741515        zmod_poly_gcd(g, numer, denom) 
     
    5871528        zmod_poly_clear(g) 
    5881529 
    5891530cdef inline unsigned long zmod_poly_leading(zmod_poly_t poly): 
     1531    """ 
     1532    Returns the leading coefficient of ``poly``. 
     1533    """ 
    5901534    return zmod_poly_get_coeff_ui(poly, zmod_poly_degree(poly)) 
    5911535 
    5921536cdef inline void zmod_poly_inc(zmod_poly_t poly, bint monic): 
     1537    """ 
     1538    Sets poly to the "next" polynomial: this is just counting in base p. 
     1539 
     1540    If monic is True then will only iterate through monic polynomials. 
     1541    """ 
    5931542    cdef long n 
    5941543    cdef long a 
    5951544    cdef long p = poly.p 
    5961545    for n from 0 <= n <= zmod_poly_degree(poly) + 1: 
    5971546        a = zmod_poly_get_coeff_ui(poly, n) + 1 
    598         if a == poly.p: 
     1547        if a == p: 
    5991548            zmod_poly_set_coeff_ui(poly, n, 0) 
    6001549        else: 
    6011550            zmod_poly_set_coeff_ui(poly, n, a) 
     
    6041553        zmod_poly_set_coeff_ui(poly, n, 0) 
    6051554        zmod_poly_set_coeff_ui(poly, n+1, 1) 
    6061555 
     1556cdef inline long zmod_poly_cmp(zmod_poly_t a, zmod_poly_t b): 
     1557    """ 
     1558    Compares `a` and `b`, returning 0 if they are equal. 
     1559 
     1560    - If the degree of `a` is less than that of `b`, returns -1. 
     1561 
     1562    - If the degree of `b` is less than that of `a`, returns 1. 
     1563 
     1564    - Otherwise, compares `a` and `b` lexicographically, starting at the leading terms. 
     1565    """ 
     1566    cdef long ad = zmod_poly_degree(a) 
     1567    cdef long bd = zmod_poly_degree(b) 
     1568    if ad < bd: 
     1569        return -1 
     1570    elif ad > bd: 
     1571        return 1 
     1572    cdef long d = zmod_poly_degree(a) 
     1573    while d >= 0: 
     1574        ad = zmod_poly_get_coeff_ui(a, d) 
     1575        bd = zmod_poly_get_coeff_ui(b, d) 
     1576        if ad < bd: 
     1577            return -1 
     1578        elif ad > bd: 
     1579            return 1 
     1580        d -= 1 
     1581    return 0 
     1582 
    6071583cdef void zmod_poly_pow(zmod_poly_t res, zmod_poly_t poly, unsigned long e): 
     1584    """ 
     1585    Raises poly to the `e`th power and stores the result in ``res``. 
     1586    """ 
    6081587    if zmod_poly_degree(poly) < 2: 
    6091588        if zmod_poly_degree(poly) == -1: 
    6101589            zmod_poly_zero(res) 
     
    6501629 
    6511630 
    6521631cdef long sqrt_mod_int(long a, long p) except -1: 
     1632    """ 
     1633    Returns the square root of a modulo p, as a long. 
     1634    """ 
    6531635    return GF(p)(a).sqrt() 
    6541636 
    6551637cdef bint zmod_poly_sqrt_check(zmod_poly_t poly):