Ticket #4302: polynomial_gf2x.patch

File polynomial_gf2x.patch, 46.0 KB (added by malb, 11 years ago)

fixes all known doctest failures

  • sage/libs/ntl/ntl_GF2X.pyx

    # HG changeset patch
    # User Martin Albrecht <malb@informatik.uni-bremen.de>
    # Date 1224185877 -7200
    # Node ID 9203a9b3ec2aa88bb050a84ac26bfed1f418fd4a
    # Parent  85bf25beff4fb6e3af81e175b055fee82167c566
    implement polynomials over GF(2) via GF2X and introduce polynomial templates
    also implemented native modular polynomial composition over GF(2) via libM4RI.
    
    diff -r 85bf25beff4f -r 9203a9b3ec2a sage/libs/ntl/ntl_GF2X.pyx
    a b  
    2323
    2424from ntl_ZZ import unpickle_class_value
    2525from ntl_GF2 cimport ntl_GF2
     26
    2627
    2728##############################################################################
    2829#
     
    123124        from sage.rings.finite_field_givaro import FiniteField_givaroElement
    124125        from sage.rings.finite_field_ntl_gf2e import FiniteField_ntl_gf2eElement
    125126        from sage.rings.ring import FiniteField
    126         from sage.rings.polynomial.polynomial_modn_dense_ntl import Polynomial_dense_mod_p
     127        from sage.rings.polynomial.polynomial_gf2x import Polynomial_GF2X
    127128
    128129        cdef long _x
    129130       
     
    141142        if PY_TYPE_CHECK(x, Integer):
    142143            #binary repr, reversed, and "["..."]" added
    143144            x="["+x.binary()[::-1].replace(""," ")+"]"
    144         elif PY_TYPE_CHECK(x, Polynomial_dense_mod_p):
    145                 x=x.ntl_ZZ_pX()
     145        elif PY_TYPE_CHECK(x, Polynomial_GF2X):
     146            x = x.list() # this is slow but cimport leads to circular imports
    146147        elif PY_TYPE_CHECK(x, FiniteField):
    147148            if x.characteristic() == 2:
    148149                x= list(x.modulus())
  • new file sage/libs/ntl/ntl_GF2X_decl.pxd

    diff -r 85bf25beff4f -r 9203a9b3ec2a sage/libs/ntl/ntl_GF2X_decl.pxd
    - +  
     1from sage.libs.ntl.ntl_GF2_decl cimport GF2_c
     2from sage.libs.ntl.ntl_ZZ_decl cimport ZZ_c
     3
     4cdef extern from "ntl_wrap.h":
     5    ctypedef struct GF2X_c "struct GF2X":
     6        pass
     7
     8    long *GF2XHexOutput_c "(&GF2X::HexOutput)" # work-around for Cython bug
     9
     10    GF2X_c* GF2X_new "New<GF2X>"()
     11    GF2X_c* GF2X_construct "Construct<GF2X>"(void *mem)
     12    void GF2X_destruct "Destruct<GF2X>"(GF2X_c *mem)
     13    void GF2X_delete "Delete<GF2X>"(GF2X_c *mem)
     14    void GF2X_from_str "_from_str<GF2X>"(GF2X_c* dest, char* s)
     15    object GF2X_to_PyString "_to_PyString<GF2X>"(GF2X_c *x)
     16    int GF2X_equal "_equal<GF2X>"(GF2X_c x, GF2X_c y)
     17    int GF2X_IsOne "IsOne"(GF2X_c x)
     18    int GF2X_IsZero "IsZero"(GF2X_c x)
     19    int GF2X_IsX "IsX"(GF2X_c x)
     20
     21    void GF2X_add "add"( GF2X_c x, GF2X_c a, GF2X_c b)
     22    void GF2X_sub "sub"( GF2X_c x, GF2X_c a, GF2X_c b)
     23    void GF2X_mul "mul"( GF2X_c x, GF2X_c a, GF2X_c b)
     24    void GF2X_negate "negate"(GF2X_c x, GF2X_c a)
     25    void GF2X_power "power"(GF2X_c t, GF2X_c x, long e)
     26    long GF2X_deg "deg"(GF2X_c x)
     27
     28    void GF2X_conv_long "conv" (GF2X_c x, long a)
     29    void GF2X_conv_GF2 "conv" (GF2X_c x, GF2_c a)
     30
     31    void GF2X_LeftShift "LeftShift"( GF2X_c r, GF2X_c a, long offset)
     32    void GF2X_RightShift "RightShift"( GF2X_c r, GF2X_c a, long offset)
     33
     34    void GF2X_DivRem "DivRem"(GF2X_c q, GF2X_c r, GF2X_c a, GF2X_c b)
     35    void GF2X_div "div" (GF2X_c q, GF2X_c a, GF2X_c b)
     36    void GF2X_rem "rem" (GF2X_c r, GF2X_c a, GF2X_c b)
     37    long GF2X_divide "divide"(GF2X_c q, GF2X_c a, GF2X_c b)
     38
     39    void GF2X_GCD "GCD" (GF2X_c r, GF2X_c a, GF2X_c b)
     40    void GF2X_XGCD "XGCD" (GF2X_c r, GF2X_c s, GF2X_c t, GF2X_c a, GF2X_c b)
     41
     42    void GF2XFromBytes(GF2X_c a, unsigned char *p, long n)
     43    void BytesFromGF2X "BytesFromGF2X" (unsigned char *p, GF2X_c a, long n)
     44
     45    GF2_c GF2X_coeff "coeff"(GF2X_c a, long i)
     46    GF2_c GF2X_LeadCoeff "LeadCoeff"(GF2X_c a)
     47    GF2_c GF2X_ConstTerm "ConstTerm"(GF2X_c a)
     48    void GF2X_SetCoeff "SetCoeff"(GF2X_c x, long i, GF2_c a)
     49    void GF2X_SetCoeff_long "SetCoeff"(GF2X_c x, long i, long a)
     50
     51    GF2X_c GF2X_diff "diff"(GF2X_c a)
     52    GF2X_c GF2X_reverse "reverse"(GF2X_c a, long hi)
     53
     54    long GF2X_weight "weight"(GF2X_c a)
     55    long GF2X_NumBits "NumBits" (GF2X_c a)
     56    long GF2X_NumBytes "NumBytes"(GF2X_c a)
     57
     58    #### GF2XFactoring
     59    void GF2X_BuildSparseIrred "BuildSparseIrred" (GF2X_c f, long n)
     60    void GF2X_BuildRandomIrred "BuildRandomIrred" (GF2X_c f, GF2X_c g)
     61
     62    #### GF2XModulus_c
     63    ctypedef struct GF2XModulus_c "struct GF2XModulus":
     64        pass
     65
     66    GF2XModulus_c* GF2XModulus_new "New<GF2XModulus>"()
     67    GF2XModulus_c* GF2XModulus_construct "Construct<GF2XModulus>"(void *mem)
     68    void GF2XModulus_destruct "Destruct<GF2XModulus>"(GF2XModulus_c *mem)
     69    void GF2XModulus_delete "Delete<GF2XModulus>"(GF2XModulus_c *mem)
     70    void GF2XModulus_from_str "_from_str<GF2XModulus>"(GF2XModulus_c* dest, char* s)
     71    void GF2XModulus_build "build"(GF2XModulus_c F, GF2X_c f) # MUST be called before using the modulus
     72    long GF2XModulus_deg "deg"(GF2XModulus_c F)
     73
     74
     75    GF2X_c GF2XModulus_GF2X "GF2X" (GF2XModulus_c m)
     76
     77    GF2X_c GF2X_IrredPolyMod "IrredPolyMod" (GF2X_c g, GF2XModulus_c F)
     78
     79    void GF2X_MulMod_pre "MulMod"(GF2X_c x, GF2X_c a, GF2X_c b, GF2XModulus_c F)
     80    void GF2X_SqrMod_pre "SqrMod"(GF2X_c x, GF2X_c a, GF2XModulus_c F)
     81    void GF2X_PowerMod_pre "PowerMod"(GF2X_c x, GF2X_c a, ZZ_c e, GF2XModulus_c F)
     82    void GF2X_PowerMod_long_pre "PowerMod"(GF2X_c x, GF2X_c a, long e, GF2XModulus_c F)
     83    void GF2X_PowerXMod_pre "PowerXMod"(GF2X_c x, ZZ_c e, GF2XModulus_c F)
     84    void GF2X_PowerXMod_long_pre "PowerXMod"(GF2X_c x, long e, GF2XModulus_c F)
     85    void GF2X_PowerXPlusAMod_pre "PowerXPlusAMod"(GF2X_c x, GF2_c a, GF2_c e, GF2XModulus_c F)
     86    void GF2X_PowerXPlusAMod_long_pre "PowerXPlusAMod"(GF2X_c x, GF2_c a, long e, GF2XModulus_c F)
     87
     88   
     89    # x = g(h) mod f; deg(h) < n
     90    void GF2X_CompMod "CompMod"(GF2X_c x, GF2X_c g, GF2X_c h, GF2XModulus_c F)
     91    # xi = gi(h) mod f (i=1,2), deg(h) < n.
     92    void GF2X_Comp2Mod "Comp2Mod"(GF2X_c x1, GF2X_c x2, GF2X_c g1, GF2X_c g2, GF2X_c h, GF2XModulus_c F)
     93
     94    # xi = gi(h) mod f (i=1,2,3), deg(h) < n.
     95    void GF2X_CompMod3 "Comp2Mod"(GF2X_c x1, GF2X_c x2, GF2X_c x3, GF2X_c g1, GF2X_c g2, GF2X_c g3, GF2X_c h, GF2XModulus_c F)
  • new file sage/libs/ntl/ntl_GF2X_linkage.pxi

    diff -r 85bf25beff4f -r 9203a9b3ec2a sage/libs/ntl/ntl_GF2X_linkage.pxi
    - +  
     1r"""
     2Linkage for arithmetic with NTL's GF2X elements.
     3
     4This file provides the backend for \class{Polynomial_GF2X} via
     5templating.
     6
     7AUTHOR:
     8    -- Martin Albrecht (2008-10): initial version
     9"""
     10#*****************************************************************************
     11#       Copyright (C) 2008 Martin Albrecht <M.R.Albrecht@rhul.ac.uk>
     12#
     13#  Distributed under the terms of the GNU General Public License (GPL)
     14#                  http://www.gnu.org/licenses/
     15#*****************************************************************************
     16
     17from sage.libs.ntl.ntl_GF2_decl cimport *, GF2_c
     18from sage.libs.ntl.ntl_GF2X_decl cimport *, GF2X_c, GF2XModulus_c
     19
     20cdef int celement_construct(GF2X_c *e, parent):
     21    """
     22    EXAMPLE:
     23        sage: P.<x> = GF(2)[]
     24    """
     25    GF2X_construct(e)
     26
     27cdef int celement_destruct(GF2X_c *e, parent):
     28    """
     29    EXAMPLE:
     30        sage: P.<x> = GF(2)[]
     31        sage: del x
     32    """
     33    GF2X_destruct(e)
     34
     35cdef int celement_gen(GF2X_c *e, long i, parent) except -2:
     36    """
     37    EXAMPLE:
     38        sage: P.<x> = GF(2)[]
     39    """
     40    cdef unsigned char g = 2
     41    GF2XFromBytes(e[0], <unsigned char *>(&g), 1)
     42
     43cdef object celement_repr(GF2X_c *e, parent):
     44    """
     45    We ignore NTL's printing.
     46
     47    EXAMPLE:
     48        sage: P.<x> = GF(2)[]
     49        sage: x
     50        x
     51    """
     52    #return GF2X_to_PyString(e)
     53    raise NotImplementedError
     54
     55cdef inline int celement_set(GF2X_c* res, GF2X_c* a, parent) except -2:
     56    """
     57    EXAMPLE:
     58        sage: P.<x> = GF(2)[]
     59        sage: y = x; y
     60        x
     61    """
     62    res[0] = a[0]
     63
     64cdef inline int celement_set_si(GF2X_c* res, long i, parent) except -2:
     65    """
     66    EXAMPLE:
     67        sage: P.<x> = GF(2)[]
     68        sage: P(0)
     69        0
     70        sage: P(2)
     71        0
     72        sage: P(1)
     73        1
     74    """
     75    GF2X_conv_long(res[0], i)
     76
     77cdef inline long celement_get_si(GF2X_c* res, parent) except -2:
     78    raise NotImplementedError
     79   
     80cdef inline bint celement_is_zero(GF2X_c* a, parent) except -2:
     81    """
     82    EXAMPLE:
     83        sage: P.<x> = GF(2)[]
     84        sage: bool(x), x.is_zero()
     85        (True, False)
     86        sage: bool(P(0)), P(0).is_zero()
     87        (False, True)
     88    """
     89    return GF2X_IsZero(a[0])
     90
     91cdef inline bint celement_is_one(GF2X_c *a, parent) except -2:
     92    """
     93    EXAMPLE:
     94        sage: P.<x> = GF(2)[]
     95        sage: x.is_one()
     96        False
     97        sage: P(1).is_one()
     98        True
     99    """
     100    return GF2X_IsOne(a[0])
     101
     102cdef inline bint celement_equal(GF2X_c *a, GF2X_c *b, parent) except -2:
     103    """
     104    EXAMPLE:
     105        sage: P.<x> = GF(2)[]
     106        sage: x == x
     107        True
     108        sage: y = x; x == y
     109        True
     110        sage: x^2 + 1 == x^2 + x
     111        False
     112    """
     113    return GF2X_equal(a[0], b[0])
     114
     115cdef inline int celement_cmp(GF2X_c *a, GF2X_c *b, parent) except -2:
     116    """
     117    EXAMPLE:
     118        sage: P.<x> = GF(2)[]
     119        sage: x != 1
     120        True
     121        sage: x < 1
     122        False
     123        sage: x > 1
     124        True
     125    """
     126    cdef bint t
     127    cdef long diff
     128    diff = GF2X_NumBits(a[0]) - GF2X_NumBits(b[0])
     129    if diff > 0:
     130        return 1
     131    elif diff == 0:
     132        t = GF2X_equal(a[0], b[0])
     133        return not t
     134    else:
     135        return -1
     136
     137cdef inline long celement_hash(GF2X_c *a, parent) except -2:
     138    """
     139    EXAMPLE:
     140        sage: P.<x> = GF(2)[]
     141        sage: {x:1}
     142        {x: 1}
     143    """
     144    cdef long _hex = GF2XHexOutput_c[0]
     145    GF2XHexOutput_c[0] = 1
     146    s = GF2X_to_PyString(a)
     147    GF2XHexOutput_c[0] = _hex
     148    return hash(s)
     149
     150cdef long celement_len(GF2X_c *a, parent) except -2:
     151    """
     152    EXAMPLE:
     153        sage: P.<x> = GF(2)[]
     154        sage: len(x)
     155        2
     156        sage: len(x+1)
     157        2
     158    """
     159    return int(GF2X_NumBits(a[0]))
     160
     161cdef inline int celement_add(GF2X_c *res, GF2X_c *a, GF2X_c *b, parent) except -2:
     162    """
     163    EXAMPLE:
     164        sage: P.<x> = GF(2)[]
     165        sage: x + 1
     166        x + 1
     167    """
     168    GF2X_add(res[0], a[0], b[0])
     169
     170cdef inline int celement_sub(GF2X_c* res, GF2X_c* a, GF2X_c* b, parent) except -2:
     171    """
     172    EXAMPLE:
     173        sage: P.<x> = GF(2)[]
     174        sage: x - 1
     175        x + 1
     176    """
     177    GF2X_sub(res[0], a[0], b[0])
     178
     179cdef inline int celement_neg(GF2X_c* res, GF2X_c* a, parent) except -2:
     180    """
     181    EXAMPLE:
     182        sage: P.<x> = GF(2)[]
     183        sage: -x
     184        x
     185    """
     186    res[0] = a[0]
     187
     188cdef inline int celement_mul(GF2X_c* res, GF2X_c* a, GF2X_c* b, parent) except -2:
     189    """
     190    EXAMPLE:
     191        sage: P.<x> = GF(2)[]
     192        sage: x*(x+1)
     193        x^2 + x
     194    """
     195    GF2X_mul(res[0], a[0], b[0])
     196
     197cdef inline int celement_div(GF2X_c* res, GF2X_c* a, GF2X_c* b, parent) except -2:
     198    """
     199    EXAMPLE:
     200        sage: P.<x> = GF(2)[]
     201    """
     202    return GF2X_divide(res[0], a[0], b[0])
     203
     204cdef inline int celement_floordiv(GF2X_c* res, GF2X_c* a, GF2X_c* b, parent) except -2:
     205    """
     206    EXAMPLE:
     207        sage: P.<x> = GF(2)[]
     208        sage: x//(x + 1)
     209        1
     210        sage: (x + 1)//x
     211        1
     212    """
     213    GF2X_div(res[0], a[0], b[0])
     214
     215cdef inline int celement_mod(GF2X_c* res, GF2X_c* a, GF2X_c* b, parent) except -2:
     216    """
     217    EXAMPLE:
     218        sage: P.<x> = GF(2)[]
     219        sage: (x^2 + 1) % x^2
     220        1
     221    """
     222    GF2X_rem(res[0], a[0], b[0])
     223
     224cdef inline int celement_quorem(GF2X_c* q, GF2X_c* r, GF2X_c* a, GF2X_c* b, parent) except -2:
     225    """
     226    EXAMPLE:
     227        sage: P.<x> = GF(2)[]
     228        sage: f = x^2 + x + 1
     229        sage: f.quo_rem(x + 1)
     230        (x, 1)
     231    """
     232    GF2X_DivRem(q[0], r[0], a[0], b[0])
     233
     234cdef inline int celement_inv(GF2X_c* res, GF2X_c* a, parent) except -2:
     235    """
     236    We ignore NTL here and use the fraction field constructor.
     237
     238    EXAMPLE:
     239        sage: P.<x> = GF(2)[]
     240    """
     241    raise NotImplementedError
     242
     243cdef inline int celement_pow(GF2X_c* res, GF2X_c* x, long e, GF2X_c *modulus, parent) except -2:
     244    """
     245    EXAMPLE:
     246        sage: P.<x> = GF(2)[]
     247        sage: x^1000
     248        x^1000
     249        sage: (x+1)^2
     250        x^2 + 1
     251        sage: (x+1)^(-2)
     252        1/(x^2 + 1)
     253        sage: f = x^9 + x^7 + x^6 + x^5 + x^4 + x^2 + x
     254        sage: h = x^10 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + 1
     255        sage: (f^2) % h
     256        x^9 + x^8 + x^7 + x^5 + x^3
     257        sage: pow(f, 2, h)
     258        x^9 + x^8 + x^7 + x^5 + x^3
     259    """
     260    cdef GF2XModulus_c mod
     261
     262    if modulus == NULL:
     263        if GF2X_IsX(x[0]):
     264                GF2X_LeftShift(res[0], x[0], e - 1)
     265        else:
     266            do_sig = GF2X_deg(x[0]) > 1e5
     267            if do_sig: _sig_on
     268            GF2X_power(res[0], x[0], e)
     269            if do_sig: _sig_off
     270    else:
     271        GF2XModulus_build(mod, modulus[0])
     272           
     273        do_sig = GF2X_deg(x[0]) > 1e5
     274        if do_sig: _sig_on
     275        GF2X_PowerMod_long_pre(res[0], x[0], e, mod)
     276        if do_sig: _sig_off
     277
     278cdef inline int celement_gcd(GF2X_c* res, GF2X_c* a, GF2X_c *b, parent) except -2:
     279    """
     280    EXAMPLE:
     281        sage: P.<x> = GF(2)[]
     282        sage: f = x*(x+1)
     283        sage: f.gcd(x+1)
     284        x + 1
     285        sage: f.gcd(x^2)
     286        x
     287    """
     288    GF2X_GCD(res[0], a[0], b[0])   
  • new file sage/libs/ntl/ntl_GF2_decl.pxd

    diff -r 85bf25beff4f -r 9203a9b3ec2a sage/libs/ntl/ntl_GF2_decl.pxd
    - +  
     1cdef extern from "ntl_wrap.h":
     2    ctypedef struct GF2_c "struct GF2":
     3        pass
     4
     5    GF2_c* GF2_new "New<GF2>"()
     6    GF2_c* GF2_construct "Construct<GF2>"(void *mem)
     7    void GF2_destruct "Destruct<GF2>"(GF2_c *mem)
     8    void GF2_delete "Delete<GF2>"(GF2_c *mem)
     9    void GF2_from_str "_from_str<GF2>"(GF2_c* dest, char* s)
     10    object GF2_to_PyString "_to_PyString<GF2>"(GF2_c *x)
     11    int GF2_equal "_equal<GF2>"(GF2_c x, GF2_c y)
     12    int GF2_IsOne "IsOne"(GF2_c x)
     13    int GF2_IsZero "IsZero"(GF2_c x)
     14
     15    void GF2_add "add"( GF2_c x, GF2_c a, GF2_c b)
     16    void GF2_sub "sub"( GF2_c x, GF2_c a, GF2_c b)
     17    void GF2_mul "mul"( GF2_c x, GF2_c a, GF2_c b)
     18    void GF2_div "div"( GF2_c x, GF2_c a, GF2_c b)
     19    void GF2_negate "negate"(GF2_c x, GF2_c a)
     20    void GF2_power "power"(GF2_c t, GF2_c x, long e)
     21    long GF2_deg "deg"(GF2_c x)
     22
     23    void GF2_conv_long "conv" (GF2_c x, long i)
     24    long GF2_conv_to_long "rep" (GF2_c x)
  • sage/matrix/matrix_mod2_dense.pyx

    diff -r 85bf25beff4f -r 9203a9b3ec2a sage/matrix/matrix_mod2_dense.pyx
    a b  
    14031403        gdImageDestroy(im)
    14041404        return unpickle_matrix_mod2_dense_v1, (r,c, data, size)
    14051405
    1406 
    14071406# Used for hashing
    14081407cdef int i, k
    14091408cdef unsigned long parity_table[256]
     
    15651564    gdImageDestroy(im)
    15661565    fclose(out)
    15671566
    1568 
    1569 
    1570 
    15711567# This is basically test code, do not call it will break Sage's
    15721568# assumptions about matrices (malb).
    15731569
  • sage/rings/polynomial/polynomial_element.pyx

    diff -r 85bf25beff4f -r 9203a9b3ec2a sage/rings/polynomial/polynomial_element.pyx
    a b  
    986986        return RingElement.__div__(self, right)
    987987       
    988988       
    989     def __pow__(self, right, dummy):
     989    def __pow__(self, right, modulus):
    990990        """
    991991        EXAMPLES:
    992992            sage: R.<x> = ZZ[]
     
    997997            x^3 - 3*x^2 + 3*x - 1           
    998998        """
    999999        if self.degree() <= 0:
    1000             return self.parent()(self[0]**right)
    1001         if right < 0:
    1002             return (~self)**(-right)
    1003         if (<Polynomial>self)._is_gen:   # special case x**n should be faster!
     1000            r = self.parent()(self[0]**right)
     1001        elif right < 0:
     1002            r = (~self)**(-right)
     1003        elif (<Polynomial>self) == self.parent().gen():   # special case x**n should be faster!
    10041004            P = self.parent()
    10051005            R = P.base_ring()
    10061006            if P.is_sparse():
    10071007                v = {right:R(1)}
    10081008            else:
    10091009                v = [R(0)]*right + [R(1)]
    1010             return self.parent()(v, check=False)
    1011         return generic_power(self, right)
     1010            r = self.parent()(v, check=False)
     1011        else:
     1012            r = generic_power(self, right)
     1013        if modulus:
     1014            return r % modulus
     1015        else:
     1016            return r
    10121017       
    10131018    def _pow(self, right):
    10141019        # TODO: fit __pow__ into the arithmetic structure
     
    10161021            return self.parent()(self[0]**right)
    10171022        if right < 0:
    10181023            return (~self)**(-right)
    1019         if (<Polynomial>self)._is_gen:   # special case x**n should be faster!
     1024        if (<Polynomial>self) == self.parent().gen():   # special case x**n should be faster!
    10201025            v = [0]*right + [1]
    10211026            return self.parent()(v, check=True)
    10221027        return generic_power(self, right)
     
    21882193            pari.set_real_precision(n)  # restore precision
    21892194        return Factorization(F, unit)
    21902195
     2196    def lcm(self, other):
     2197        """
     2198        Let f and g be two polynomials.  Then this function
     2199        returns the monic least common multiple of f and g.
     2200        """
     2201        f = self*other
     2202        g = self.gcd(other)
     2203        q = f//g
     2204        return ~(q.leading_coefficient())*q
     2205
    21912206    def _lcm(self, other):
    21922207        """
    21932208        Let f and g be two polynomials.  Then this function
     
    21972212        g = self.gcd(other)
    21982213        q = f//g 
    21992214        return ~(q.leading_coefficient())*q  # make monic  (~ is inverse in python)
     2215
     2216    def is_primitive(self):
     2217        """
     2218        Identifies whether a polynomial is primitive.
     2219        A polynomial can only be primitive if it is irreducible.
     2220
     2221        EXAMPLES:
     2222            sage: R.<x> = GF(2)['x']
     2223            sage: f = x^4+x^3+x^2+x+1
     2224            sage: f.is_irreducible(), f.is_primitive()
     2225            (True, False)
     2226            sage: f = x^3+x+1
     2227            sage: f.is_irreducible(), f.is_primitive()
     2228            (True, True)
     2229            sage: R.<x> = GF(3)[]
     2230            sage: f = x^3-x+1
     2231            sage: f.is_irreducible(), f.is_primitive()
     2232            (True, True)
     2233            sage: f = x^2+1
     2234            sage: f.is_irreducible(), f.is_primitive()
     2235            (True, False)
     2236            sage: R.<x> = GF(5)[]
     2237            sage: f = x^2+x+1
     2238            sage: f.is_primitive()
     2239            False
     2240            sage: f = x^2-x+2
     2241            sage: f.is_primitive()
     2242            True
     2243        """
     2244        if not self.is_irreducible():
     2245            return False
     2246        p = self.parent().characteristic()
     2247        n = p ** self.degree() - 1
     2248        y = self.parent().quo(self).gen()
     2249        for d in n.prime_divisors():
     2250            if ( y ** (n//d) ) == 1:
     2251                return False
     2252        return True
    22002253
    22012254    def is_constant(self):
    22022255        """
  • new file sage/rings/polynomial/polynomial_gf2x.pxd

    diff -r 85bf25beff4f -r 9203a9b3ec2a sage/rings/polynomial/polynomial_gf2x.pxd
    - +  
     1from sage.libs.ntl.ntl_GF2X_decl cimport GF2X_c
     2
     3ctypedef GF2X_c celement
     4
     5include "polynomial_template_header.pxi"
     6
     7cdef class Polynomial_GF2X(Polynomial_template):
     8    pass
     9   
  • new file sage/rings/polynomial/polynomial_gf2x.pyx

    diff -r 85bf25beff4f -r 9203a9b3ec2a sage/rings/polynomial/polynomial_gf2x.pyx
    - +  
     1"""
     2Univariate Polynomials over GF(2) via NTL's GF2X.
     3
     4AUTHOR:
     5    -- Martin Albrecht (2008-10) initial implementation
     6"""
     7
     8include "../../libs/ntl/ntl_GF2X_linkage.pxi"
     9
     10include "polynomial_template.pxi"
     11
     12from sage.libs.all import pari
     13
     14#ctypedef unsigned long long word "word"
     15
     16from sage.matrix.matrix_mod2_dense cimport mzd_write_bit, mzd_read_bit, Matrix_mod2_dense, word
     17
     18cdef class Polynomial_GF2X(Polynomial_template):
     19    """
     20    Univariate Polynomials over GF(2) via NTL's GF2X.
     21
     22    EXAMPLE:
     23        sage: P.<x> = GF(2)[]
     24        sage: x^3 + x^2 + 1
     25        x^3 + x^2 + 1
     26    """
     27    def __init__(self, parent, x=None, check=True, is_gen=False, construct=False):
     28        """
     29        Create a new univariate polynomials over GF(2).
     30       
     31        EXAMPLE:
     32            sage: P.<x> = GF(2)[]
     33            sage: x^3 + x^2 + 1
     34            x^3 + x^2 + 1
     35        """
     36        try:
     37            if x.parent() is parent.base_ring() or x.parent() == parent.base_ring():
     38                x = int(x)
     39        except AttributeError:
     40            pass
     41        Polynomial_template.__init__(self, parent, x, check, is_gen, construct)
     42
     43    def __getitem__(self, int i):
     44        """
     45        EXAMPLE:
     46            sage: P.<x> = GF(2)[]
     47            sage: f = x^3 + x^2 + 1; f
     48            x^3 + x^2 + 1
     49            sage: f[0]
     50            1
     51            sage: f[1]
     52            0
     53        """
     54        cdef long c
     55        if 0 <= i < GF2X_NumBits(self.x):
     56            c = GF2_conv_to_long(GF2X_coeff(self.x, i))
     57        return self._parent.base_ring()(c)
     58
     59    def _pari_(self, variable=None):
     60        """
     61        EXAMPLE:
     62            sage: P.<x> = GF(2)[]
     63            sage: f = x^3 + x^2 + 1
     64            sage: pari(f)
     65            Mod(1, 2)*x^3 + Mod(1, 2)*x^2 + Mod(1, 2)
     66        """
     67        #TODO: put this in a superclass
     68        parent = self._parent
     69        if variable is None:
     70            variable = parent.variable_name()
     71        return pari(self.list()).Polrev(variable) * pari(1).Mod(2)
     72
     73    def modular_composition(Polynomial_GF2X self, Polynomial_GF2X g, Polynomial_GF2X h, algorithm=None):
     74        """
     75        Compute f(g) % h.
     76
     77        Both implementations Use Brent-Kung's Algorithm 2.1 (Fast
     78        Algorithms for Manipulation Formal Power Series, JACM 1978)
     79
     80        INPUT:
     81            g -- a polynomial
     82            h -- a polynomial
     83            algorithm -- either 'native' or 'ntl' (default: 'native')
     84
     85        EXAMPLE:
     86            sage: P.<x> = GF(2)[]
     87            sage: r = 279
     88            sage: f = x^r + x +1
     89            sage: g = x^r
     90            sage: g.modular_composition(g, f) == g(g) % f
     91            True
     92
     93        AUTHORS:
     94             -- Paul Zimmermann (2008-10) initial implementation
     95             -- Martin Albrecht (2008-10) performance improvements
     96        """
     97        if g.parent() is not self.parent() or h.parent() is not self.parent():
     98            raise TypeError("Parents of the first three parameters must match.")
     99
     100        from sage.misc.misc import verbose, cputime
     101        from sage.calculus.calculus import ceil
     102        from sage.matrix.constructor import Matrix
     103        from sage.rings.all import FiniteField as GF
     104
     105        cdef Polynomial_GF2X res
     106        cdef GF2XModulus_c modulus
     107        GF2XModulus_build(modulus, (<Polynomial_GF2X>h).x)
     108
     109        res = <Polynomial_GF2X>PY_NEW(Polynomial_GF2X)
     110        res._parent = self._parent
     111
     112        if algorithm == "ntl":
     113            t = cputime()
     114            _sig_on
     115            GF2X_CompMod(res.x, self.x, g.x, modulus)
     116            _sig_off
     117            verbose("NTL %5.3f s"%cputime(t),level=1)
     118            return res
     119
     120        cdef Py_ssize_t i, j, k, l, n, maxlength
     121        cdef Matrix_mod2_dense F, G, H
     122
     123        cdef GF2X_c _f = (<Polynomial_GF2X>self).x
     124        cdef GF2X_c _g = (<Polynomial_GF2X>g).x
     125        cdef GF2X_c gpow, tt
     126        GF2X_conv_long(gpow, 1)
     127
     128        maxlength = GF2X_NumBits(_f)
     129
     130        t = cputime()
     131
     132        n = h.degree()
     133
     134        k = ceil(Integer(n+1).sqrt_approx())
     135        l = ceil((self.degree() + 1) / k)
     136
     137        # we store all matrices transposed for performance reasons
     138        G = <Matrix_mod2_dense>Matrix(GF(2), k, n)
     139
     140        # first compute g^j mod h, 2 <= j < k
     141        for j in range(0, k):
     142            for i from 0 <= i < GF2X_NumBits(gpow):
     143                mzd_write_bit(G._entries, j, i, GF2_conv_to_long(GF2X_coeff(gpow, i)))
     144            #gpow = (gpow * g) % h # we'll need g^k below
     145            GF2X_MulMod_pre(gpow, gpow, _g, modulus)
     146        verbose("G %d x %d %5.3f s"%(G.nrows(), G.ncols(),cputime(t)),level=1)
     147
     148        # split f in chunks of degree < k
     149        t = cputime()
     150        F = <Matrix_mod2_dense>Matrix(GF(2), l, k)
     151        for j in range(0, l):
     152            if j*k+k <= maxlength:
     153                for i from j*k <= i < j*k+k:
     154                    mzd_write_bit(F._entries, j, i-j*k, GF2_conv_to_long(GF2X_coeff(_f, i)))
     155            else:
     156                for i from j*k <= i < maxlength:
     157                    mzd_write_bit(F._entries, j, i-j*k, GF2_conv_to_long(GF2X_coeff(_f, i)))
     158               
     159        verbose("F %d x %d %5.3f s"%(F.nrows(), F.ncols(), cputime(t)),level=1)
     160
     161        t = cputime()
     162        H = <Matrix_mod2_dense>(F * G)
     163        verbose("H %d x %d %5.3f s"%(H.nrows(), H.ncols(), cputime(t)),level=1)
     164
     165        t = cputime()
     166        # H is a n x l matrix now H[i,j] = sum(G[i,m]*F[m,j],
     167        # m=0..k-1) = sum(g^m[i] * f[j*k+m], m=0..k-1) where g^m[i] is
     168        # the coefficient of degree i in g^m and f[j*k+m] is the
     169        # coefficient of degree j*k+m in f thus f[j*k+m]*g^m[i] should
     170        # be multiplied by g^(j*k) gpow = (g^k) % h
     171       
     172        GF2X_conv_long(res.x, 0)
     173        j = l - 1
     174        while j >= 0:
     175            #res = (res * gpow) % h
     176            GF2X_MulMod_pre(res.x, res.x, gpow, modulus)
     177
     178            # res = res + parent([H[j,i] for i in range(0,n)])
     179            GF2X_conv_long(tt, 0)
     180            for i from 0<= i < n:
     181                GF2X_SetCoeff_long(tt, i, mzd_read_bit(H._entries, j, i))
     182            GF2X_add(res.x, res.x, tt)
     183            j = j - 1
     184
     185        verbose("Res %5.3f s"%cputime(t),level=1)
     186        return res
  • sage/rings/polynomial/polynomial_modn_dense_ntl.pyx

    diff -r 85bf25beff4f -r 9203a9b3ec2a sage/rings/polynomial/polynomial_modn_dense_ntl.pyx
    a b  
    16841684    #    self.parent()._ntl_set_modulus()
    16851685    #    F = [(self.parent()(f, construct=True), n) for f, n in M.ntl_ZZ_pX().factor(verbose)]
    16861686    #    return factorization.Factorization(F)
    1687 
    1688     def is_primitive(self):
    1689         """
    1690         Identifies whether a polynomial is primitive.
    1691         A polynomial can only be primitive if it is irreducible.
    1692 
    1693         EXAMPLES:
    1694             sage: R.<x> = GF(2)['x']
    1695             sage: f = x^4+x^3+x^2+x+1
    1696             sage: f.is_irreducible(), f.is_primitive()
    1697             (True, False)
    1698             sage: f = x^3+x+1
    1699             sage: f.is_irreducible(), f.is_primitive()
    1700             (True, True)
    1701             sage: R.<x> = GF(3)[]
    1702             sage: f = x^3-x+1
    1703             sage: f.is_irreducible(), f.is_primitive()
    1704             (True, True)
    1705             sage: f = x^2+1
    1706             sage: f.is_irreducible(), f.is_primitive()
    1707             (True, False)
    1708             sage: R.<x> = GF(5)[]
    1709             sage: f = x^2+x+1
    1710             sage: f.is_primitive()
    1711             False
    1712             sage: f = x^2-x+2
    1713             sage: f.is_primitive()
    1714             True
    1715         """
    1716         if not self.is_irreducible():
    1717             return False
    1718         p = self.parent().characteristic()
    1719         n = p ** self.degree() - 1
    1720         y = self.parent().quo(self).gen()
    1721         for d in n.prime_divisors():
    1722             if ( y ** (n//d) ) == 1:
    1723                 return False
    1724         return True
    1725    
  • sage/rings/polynomial/polynomial_ring.py

    diff -r 85bf25beff4f -r 9203a9b3ec2a sage/rings/polynomial/polynomial_ring.py
    a b  
    11351135                raise TypeError,"Unable to coerce string"
    11361136        elif hasattr(x, '_polynomial_'):
    11371137            return x._polynomial_(self)
    1138         return polynomial_modn_dense_ntl.Polynomial_dense_mod_p(self, x, check, is_gen,construct=construct)
     1138        if self.modulus() == 2:
     1139            import sage.rings.polynomial.polynomial_gf2x as polynomial_gf2x
     1140            return polynomial_gf2x.Polynomial_GF2X(self, x, check, is_gen,construct=construct)
     1141        else:
     1142            return polynomial_modn_dense_ntl.Polynomial_dense_mod_p(self, x, check, is_gen,construct=construct)
    11391143
    11401144
    11411145def polygen(ring_or_element, name="x"):
  • new file sage/rings/polynomial/polynomial_template.pxi

    diff -r 85bf25beff4f -r 9203a9b3ec2a sage/rings/polynomial/polynomial_template.pxi
    - +  
     1"""
     2Polynomial Template for C/C++ Library Interfaces
     3
     4AUTHOR:
     5    -- Robert Bradshaw (2008-10) original idea for templating
     6    -- Martin Albrecht (2008-10) initial implementation
     7
     8This file implements a simple templating engine for linking univariate
     9polynomials to their C/C++ library implementations. It requires a
     10'linkage' file which implements the \code{celement_} functions (see
     11\code{sage.libs.ntl.ntl_GF2X_linkage} for an example). Both parts are
     12then pluygged together by inclusion of the linkage file when
     13inheriting from this class. See
     14\code{sage.rings.polynomial.polynomial_gf2x} for an example.
     15
     16We illustrate the generic glueing using univariate polynomials over
     17GF(2).
     18
     19NOTE:
     20Implementations using this template MUST implement coercion from base
     21ring elements and \code{__getitem__}. See \code{Polynomial_GF2X} for an example.
     22"""
     23#*****************************************************************************
     24#       Copyright (C) 2008 Martin Albrecht <M.R.Albrecht@rhul.ac.uk>
     25#       Copyright (C) 2008 Robert Bradshaw
     26#
     27#  Distributed under the terms of the GNU General Public License (GPL)
     28#                  http://www.gnu.org/licenses/
     29#*****************************************************************************
     30
     31include "../../ext/interrupt.pxi"
     32include "../../ext/stdsage.pxi"
     33
     34from sage.rings.polynomial.polynomial_element cimport Polynomial
     35from sage.structure.element cimport ModuleElement, Element, RingElement
     36from sage.rings.integer cimport Integer
     37from sage.libs.all import pari_gen
     38
     39def make_element(parent, args):
     40    return parent(*args)
     41
     42cdef class Polynomial_template(Polynomial):
     43    def __init__(self, parent, x=None, check=True, is_gen=False, construct=False):
     44        """
     45        EXAMPLE:
     46            sage: P.<x> = GF(2)[]
     47            sage: P(0)
     48            0
     49            sage: P(GF(2)(1))
     50            1
     51            sage: P(3)
     52            1
     53            sage: P([1,0,1])
     54            x^2 + 1
     55            sage: P(map(GF(2),[1,0,1]))
     56            x^2 + 1
     57        """
     58        cdef celement gen, monomial, coeff
     59        cdef Py_ssize_t deg
     60
     61        Polynomial.__init__(self, parent, is_gen=is_gen)
     62
     63        if is_gen:
     64            celement_gen(&self.x, 0, parent)
     65
     66        elif PY_TYPE_CHECK(x, Polynomial_template):
     67            try:
     68                celement_set(&self.x, &(<Polynomial_template>x).x, parent)
     69            except NotImplementedError:
     70                raise TypeError("%s not understood."%x)
     71
     72        elif PY_TYPE_CHECK(x, int) or PY_TYPE_CHECK(x, Integer):
     73            try:
     74                celement_set_si(&self.x, int(x), parent)
     75            except NotImplementedError:
     76                raise TypeError("%s not understood."%x)
     77
     78        elif PY_TYPE_CHECK(x, list) or PY_TYPE_CHECK(x, tuple):
     79            parent = (<Polynomial_template>self)._parent
     80
     81            celement_set_si(&self.x, 0, parent)
     82            celement_gen(&gen, 0, parent)
     83
     84            deg = 0
     85            for e in x:
     86                # r += parent(e)*power
     87                celement_pow(&monomial, &gen, deg, NULL, parent)
     88                coeff = (<Polynomial_template>parent(e)).x
     89                celement_mul(&monomial, &coeff, &monomial, parent)
     90                celement_add(&self.x, &self.x, &monomial, parent)
     91                deg += 1
     92
     93        elif PY_TYPE_CHECK(x, pari_gen):
     94            k = (<Polynomial_template>self)._parent.base_ring()
     95            x = [k(w) for w in x.Vecrev()]
     96            Polynomial_template.__init__(self, parent, x, check=True, is_gen=False, construct=construct)
     97        elif PY_TYPE_CHECK(x, Polynomial):
     98            k = (<Polynomial_template>self)._parent.base_ring()
     99            x = [k(w) for w in list(x)]
     100            Polynomial_template.__init__(self, parent, x, check=True, is_gen=False, construct=construct)
     101        else:
     102            raise TypeError("Coercion from parent %s not supported."%x.parent())
     103
     104    def __reduce__(self):
     105        """
     106        EXAMPLE:
     107            sage: P.<x> = GF(2)[]
     108            sage: loads(dumps(x)) == x
     109            True
     110        """
     111        return make_element, ((<Polynomial_template>self)._parent, (self.list(), False, self.is_gen()))
     112
     113    def list(self):
     114        """
     115        EXAMPLE:
     116            sage: P.<x> = GF(2)[]
     117            sage: x.list()
     118            [0, 1]
     119            sage: list(x)
     120            [0, 1]
     121        """
     122        cdef Py_ssize_t i
     123        return [self[i] for i in range(celement_len(&self.x,(<Polynomial_template>self)._parent))]
     124
     125    def __cinit__(self):
     126        """
     127        EXAMPLE:
     128            sage: P.<x> = GF(2)[]
     129        """
     130        celement_construct(&self.x, (<Polynomial_template>self)._parent)
     131
     132    def __dealloc__(self):
     133        """
     134        EXAMPLE:
     135            sage: P.<x> = GF(2)[]
     136            sage: del x
     137        """
     138        celement_destruct(&self.x, (<Polynomial_template>self)._parent)
     139
     140    cpdef ModuleElement _add_(self, ModuleElement right):
     141        """
     142        EXAMPLE:
     143            sage: P.<x> = GF(2)[]
     144            sage: x + 1
     145            x + 1
     146        """
     147        cdef Polynomial_template r = <Polynomial_template>PY_NEW(self.__class__)
     148        r._parent = (<Polynomial_template>self)._parent
     149        celement_add(&r.x, &(<Polynomial_template>self).x, &(<Polynomial_template>right).x, (<Polynomial_template>self)._parent)
     150        return r
     151
     152    cpdef ModuleElement _sub_(self, ModuleElement right):
     153        """
     154        EXAMPLE:
     155            sage: P.<x> = GF(2)[]
     156            sage: x - 1
     157            x + 1
     158        """
     159        cdef Polynomial_template r = <Polynomial_template>PY_NEW(self.__class__)
     160        r._parent = (<Polynomial_template>self)._parent
     161        celement_add(&r.x, &(<Polynomial_template>self).x, &(<Polynomial_template>right).x, (<Polynomial_template>self)._parent)
     162        return r
     163
     164    def __neg__(self):
     165        """
     166        EXAMPLE:
     167            sage: P.<x> = GF(2)[]
     168            sage: -x
     169            x
     170        """
     171        cdef Polynomial_template r = <Polynomial_template>PY_NEW(self.__class__)
     172        r._parent = (<Polynomial_template>self)._parent
     173        celement_neg(&r.x, &self.x, (<Polynomial_template>self)._parent)
     174        return r
     175
     176    cpdef RingElement _mul_(self, RingElement right):
     177        """
     178        EXAMPLE:
     179            sage: P.<x> = GF(2)[]
     180            sage: x*(x+1)
     181            x^2 + x
     182        """
     183        cdef Polynomial_template r = <Polynomial_template>PY_NEW(self.__class__)
     184        r._parent = (<Polynomial_template>self)._parent
     185        celement_mul(&r.x, &(<Polynomial_template>self).x, &(<Polynomial_template>right).x, (<Polynomial_template>self)._parent)
     186        return r
     187
     188    def gcd(self, Polynomial_template other):
     189        """
     190        EXAMPLE:
     191            sage: P.<x> = GF(2)[]
     192            sage: f = x*(x+1)
     193            sage: f.gcd(x+1)
     194            x + 1
     195            sage: f.gcd(x^2)
     196            x
     197        """
     198        cdef Polynomial_template r = <Polynomial_template>PY_NEW(self.__class__)
     199        r._parent = (<Polynomial_template>self)._parent
     200        celement_gcd(&r.x, &(<Polynomial_template>self).x, &(<Polynomial_template>other).x, (<Polynomial_template>self)._parent)
     201        return r
     202
     203    def __floordiv__(self, right):
     204        """
     205        EXAMPLE:
     206            sage: P.<x> = GF(2)[]
     207            sage: x//(x + 1)
     208            1
     209            sage: (x + 1)//x
     210            1
     211        """
     212        right = (<Polynomial_template>self)._parent._coerce_(right)
     213        cdef Polynomial_template r = <Polynomial_template>PY_NEW(self.__class__)
     214        r._parent = (<Polynomial_template>self)._parent
     215        celement_floordiv(&r.x, &(<Polynomial_template>self).x, &(<Polynomial_template>right).x, (<Polynomial_template>self)._parent)
     216        return r
     217
     218    def __mod__(self, other):
     219        """
     220        EXAMPLE:
     221            sage: P.<x> = GF(2)[]
     222            sage: (x^2 + 1) % x^2
     223            1
     224        """
     225        other = (<Polynomial_template>self)._parent._coerce_(other)
     226        cdef Polynomial_template r = <Polynomial_template>PY_NEW(self.__class__)
     227        r._parent = (<Polynomial_template>self)._parent
     228        celement_mod(&r.x, &(<Polynomial_template>self).x, &(<Polynomial_template>other).x, (<Polynomial_template>self)._parent)
     229        return r
     230
     231    def quo_rem(self, right):
     232        """
     233        EXAMPLE:
     234            sage: P.<x> = GF(2)[]
     235            sage: f = x^2 + x + 1
     236            sage: f.quo_rem(x + 1)
     237            (x, 1)
     238        """
     239        right = (<Polynomial_template>self)._parent._coerce_(right)
     240        cdef Polynomial_template q = <Polynomial_template>PY_NEW(self.__class__)
     241        q._parent = (<Polynomial_template>self)._parent
     242        cdef Polynomial_template r = <Polynomial_template>PY_NEW(self.__class__)
     243        r._parent = (<Polynomial_template>self)._parent
     244        celement_quorem(&q.x, &r.x, &(<Polynomial_template>self).x, &(<Polynomial_template>right).x, (<Polynomial_template>self)._parent)
     245        return q,r
     246       
     247    def __long__(self):
     248        """
     249        EXAMPLE:
     250            sage: P.<x> = GF(2)[]
     251            sage: int(x)
     252            Traceback (most recent call last):
     253            ...
     254            TypeError: cannot coerce nonconstant polynomial to int
     255
     256            sage: int(P(1))
     257            1
     258        """
     259        if celement_len(&self.x, (<Polynomial_template>self)._parent) > 1:
     260            raise ValueError("Cannot coerce polynomial with degree %d to integer."%(self.degree()))
     261        return int(self[0])
     262
     263    def __nonzero__(self):
     264        """
     265        EXAMPLE:
     266            sage: P.<x> = GF(2)[]
     267            sage: bool(x), x.is_zero()
     268            (True, False)
     269            sage: bool(P(0)), P(0).is_zero()
     270            (False, True)
     271        """
     272        return not celement_is_zero(&self.x, (<Polynomial_template>self)._parent)
     273
     274    def __richcmp__(left, right, int op):
     275        """
     276        EXAMPLE:
     277            sage: P.<x> = GF(2)[]
     278            sage: x != 1
     279            True
     280            sage: x < 1
     281            False
     282            sage: x > 1
     283            True
     284        """
     285        return (<Element>left)._richcmp(right, op)
     286   
     287    cdef int _cmp_c_impl(left, Element right) except -2:
     288        """
     289        EXAMPLE:
     290            sage: P.<x> = GF(2)[]
     291        """
     292        return celement_cmp(&(<Polynomial_template>left).x, &(<Polynomial_template>right).x, (<Polynomial_template>left)._parent)
     293
     294    def __hash__(self):
     295        """
     296        EXAMPLE:
     297            sage: P.<x> = GF(2)[]
     298            sage: {x:1}
     299            {x: 1}
     300        """
     301        return celement_hash(&self.x, (<Polynomial_template>self)._parent)
     302
     303    def __len__(self):
     304        """
     305        EXAMPLE:
     306            sage: P.<x> = GF(2)[]
     307            sage: P.<x> = GF(2)[]
     308            sage: len(x)
     309            2
     310            sage: len(x+1)
     311            2
     312        """
     313        return celement_len(&self.x, (<Polynomial_template>self)._parent)
     314
     315    def __pow__(self, ee, modulus):
     316        """
     317        EXAMPLE:
     318            sage: P.<x> = GF(2)[]
     319            sage: P.<x> = GF(2)[]
     320            sage: x^1000
     321            x^1000
     322            sage: (x+1)^2
     323            x^2 + 1
     324            sage: (x+1)^(-2)
     325            1/(x^2 + 1)
     326            sage: f = x^9 + x^7 + x^6 + x^5 + x^4 + x^2 + x
     327            sage: h = x^10 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + 1
     328            sage: (f^2) % h
     329            x^9 + x^8 + x^7 + x^5 + x^3
     330            sage: pow(f, 2, h)
     331            x^9 + x^8 + x^7 + x^5 + x^3
     332        """
     333        if not PY_TYPE_CHECK(self, Polynomial_template):
     334            raise NotImplementedError("%s^%s not defined."%(ee,self))
     335        cdef bint recip = 0, do_sig
     336        cdef long e = ee
     337        if e != ee:
     338            raise TypeError("Only integral powers defined.")
     339        elif e < 0:
     340            recip = 1 # delay because powering frac field elements is slow
     341            e = -e
     342        if not self:
     343            if e == 0:
     344                raise ArithmeticError, "0^0 is undefined."
     345        cdef Polynomial_template r = <Polynomial_template>PY_NEW(self.__class__)
     346        r._parent = (<Polynomial_template>self)._parent
     347
     348        if modulus is None:
     349            celement_pow(&r.x, &(<Polynomial_template>self).x, e, NULL, (<Polynomial_template>self)._parent)
     350        else:
     351            modulus = (<Polynomial_template>self)._parent._coerce_(modulus)
     352            celement_pow(&r.x, &(<Polynomial_template>self).x, e, &(<Polynomial_template>modulus).x, (<Polynomial_template>self)._parent)
     353        if recip:
     354            return ~r
     355        else:
     356            return r
     357       
     358    def is_gen(self):
     359        """
     360        EXAMPLE:
     361            sage: P.<x> = GF(2)[]
     362            sage: x.is_gen()
     363            True
     364            sage: (x+1).is_gen()
     365            False
     366        """
     367        cdef celement gen
     368        celement_gen(&gen, 0, (<Polynomial_template>self)._parent)
     369        return celement_equal(&self.x, &gen, (<Polynomial_template>self)._parent)
     370
     371    def shift(self, int n):
     372        """
     373        EXAMPLE:
     374            sage: P.<x> = GF(2)[]
     375            sage: f = x^3 + x^2 + 1
     376            sage: f.shift(1)
     377            x^4 + x^3 + x
     378            sage: f.shift(-1)
     379            x^2 + x
     380        """
     381        cdef celement gen
     382        cdef Polynomial_template r
     383        if n == 0:
     384            return self
     385
     386        parent = (<Polynomial_template>self)._parent
     387        celement_gen(&gen, 0, parent)
     388        celement_pow(&gen, &gen, abs(n), NULL, parent)
     389        r = <Polynomial_template>PY_NEW(self.__class__)
     390        r._parent = parent
     391       
     392        if n > 0:
     393            celement_mul(&r.x, &self.x, &gen, parent)
     394        else:
     395            celement_floordiv(&r.x, &self.x, &gen, parent)
     396        return r
     397
     398    def __lshift__(self, int n):
     399        """
     400        EXAMPLE:
     401            sage: P.<x> = GF(2)[]
     402            sage: f = x^3 + x^2 + 1
     403            sage: f << 1
     404            x^4 + x^3 + x
     405        """
     406        if not PY_TYPE_CHECK(self, Polynomial_template):
     407            raise TypeError("Cannot %s << %n."%(self, n))
     408        cdef celement gen
     409        cdef Polynomial_template r
     410        if n == 0:
     411            return self
     412        elif n < 0:
     413            return self >> -n
     414
     415        parent = (<Polynomial_template>self)._parent
     416        celement_gen(&gen, 0, parent)
     417        celement_pow(&gen, &gen, n, NULL, parent)
     418        r = <Polynomial_template>PY_NEW(self.__class__)
     419        r._parent = parent
     420        celement_mul(&r.x, &(<Polynomial_template>self).x, &gen, parent)
     421        return r
     422
     423    def __rshift__(self, int n):
     424        """
     425        EXAMPLE:
     426            sage: P.<x> = GF(2)[]
     427        """
     428        if not PY_TYPE_CHECK(self, Polynomial_template):
     429            raise TypeError("Cannot %s >> %n."%(self, n))
     430        cdef celement gen
     431        cdef Polynomial_template r
     432        if n == 0:
     433            return self
     434        elif n < 0:
     435            return self >> -n
     436
     437        parent = (<Polynomial_template>self)._parent
     438        celement_gen(&gen, 0, parent)
     439        celement_pow(&gen, &gen, n, NULL, parent)
     440        r = <Polynomial_template>PY_NEW(self.__class__)
     441        r._parent = parent
     442       
     443        celement_floordiv(&r.x, &(<Polynomial_template>self).x, &gen, parent)
     444        return r
     445
     446    def is_zero(self):
     447        """
     448        EXAMPLE:
     449            sage: P.<x> = GF(2)[]
     450        """
     451        return celement_is_zero(&self.x, (<Polynomial_template>self)._parent)
     452
     453    def is_one(self):
     454        """
     455        EXAMPLE:
     456            sage: P.<x> = GF(2)[]
     457        """
     458        return celement_is_one(&self.x, (<Polynomial_template>self)._parent)
     459
     460    def degree(self):
     461        """
     462        EXAMPLE:
     463            sage: P.<x> = GF(2)[]
     464        """
     465        return Integer(celement_len(&self.x, (<Polynomial_template>self)._parent)-1)
     466
     467    def truncate(self, n):
     468        """
     469        Returns this polynomial mod $x^n$.
     470       
     471        EXAMPLES:
     472            sage: R.<x> =GF(2)[]
     473            sage: f = sum(x^n for n in range(10)); f
     474            x^9 + x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1
     475            sage: f.truncate(6)
     476            x^5 + x^4 + x^3 + x^2 + x + 1
     477        """
     478        if n < 0:
     479            raise ValueError(" n must be >= 0.")
     480        parent = (<Polynomial_template>self)._parent
     481        cdef celement gen
     482        celement_gen(&gen, 0, parent)
     483        celement_pow(&gen, &gen, n, NULL, parent)
     484
     485        cdef Polynomial_template r = <Polynomial_template>PY_NEW(self.__class__)
     486        r._parent = parent
     487        celement_mod(&r.x, &self.x, &gen, parent)
     488        return r
  • new file sage/rings/polynomial/polynomial_template_header.pxi

    diff -r 85bf25beff4f -r 9203a9b3ec2a sage/rings/polynomial/polynomial_template_header.pxi
    - +  
     1"""
     2Polynomial Template for C/C++ Library Interfaces
     3"""
     4
     5from sage.rings.polynomial.polynomial_element cimport Polynomial
     6
     7cdef class Polynomial_template(Polynomial):
     8    cdef celement x
     9
  • setup.py

    diff -r 85bf25beff4f -r 9203a9b3ec2a setup.py
    a b  
    917917                 language = 'c++',
    918918                 include_dirs=debian_include_dirs + ['sage/libs/ntl/']), \
    919919
     920    Extension('sage.rings.polynomial.polynomial_gf2x',
     921                 sources = ['sage/rings/polynomial/polynomial_gf2x.pyx'],
     922                 libraries = ['ntl', 'stdc++', 'gmp'],
     923                 language = 'c++',
     924                 include_dirs=debian_include_dirs + ['sage/libs/ntl/']), \
     925
    920926    Extension('sage.rings.polynomial.polynomial_real_mpfr_dense',
    921927                 sources = ['sage/rings/polynomial/polynomial_real_mpfr_dense.pyx'],
    922928                 libraries = ['mpfr', 'gmp']), \