Ticket #7931: 7931_common_superclass.patch

File 7931_common_superclass.patch, 16.5 KB (added by roed, 9 years ago)

Apply on top of 7931_nth_root.2.patch; moves _nth_root_common to FiniteRingElement?, a new superclass of IntegerMod_abstract and the finite field elements

  • sage/rings/finite_rings/all.py

    # HG changeset patch
    # User David Roe <roed@math.harvard.edu>
    # Date 1285725069 14400
    # Node ID 52506cc26942ad30ab3fd8cb0c794d2d67b84f86
    # Parent  6d6c6a580546f87b06e55064ccd269a9e001abb6
    #7931: Creates a common superclass, FiniteRingElement for finite rings to reduce code duplication.
    
    diff -r 6d6c6a580546 -r 52506cc26942 sage/rings/finite_rings/all.py
    a b  
    2222                          conway_polynomial, exists_conway_polynomial)
    2323GF = FiniteField
    2424
    25 from element_base import FiniteFieldElement, is_FiniteFieldElement
     25from element_base import FinitePolyExtElement as FiniteFieldElement # for backward compatibility; is this needed?
     26from element_base import is_FiniteFieldElement
    2627
  • sage/rings/finite_rings/element_base.pxd

    diff -r 6d6c6a580546 -r 52506cc26942 sage/rings/finite_rings/element_base.pxd
    a b  
    1 from sage.structure.element cimport FieldElement
     1from sage.structure.element cimport CommutativeRingElement
    22
    3 cdef class FiniteFieldElement(FieldElement):
     3cdef class FiniteRingElement(CommutativeRingElement):
    44    pass
     5
     6cdef class FinitePolyExtElement(FiniteRingElement):
     7    pass
  • sage/rings/finite_rings/element_base.pyx

    diff -r 6d6c6a580546 -r 52506cc26942 sage/rings/finite_rings/element_base.pyx
    a b  
    2929    from sage.rings.finite_rings.finite_field_base import is_FiniteField
    3030    return isinstance(x, Element) and is_FiniteField(x.parent())
    3131
    32 cdef class FiniteFieldElement(FieldElement):
     32cdef class FiniteRingElement(CommutativeRingElement):
     33    def _nth_root_common(self, n, all, algorithm, cunningham):
     34        """
     35        This function exists to reduce code duplication between finite field nth roots and integer_mod nth roots.
     36       
     37        The inputs are described there.
     38       
     39        TESTS::
     40       
     41            sage: a = Zmod(17)(13)
     42            sage: a._nth_root_common(4, True, "Johnston", False)
     43            [3, 5, 14, 12]
     44        """
     45        K = self.parent()
     46        q = K.order()
     47        if self.is_one():
     48            gcd = n.gcd(q-1)
     49            if gcd == 1:
     50                if all: return [self]
     51                else: return self
     52            else:
     53                # the following may eventually be improved to not need a multiplicative generator.
     54                g = K.multiplicative_generator()
     55                q1overn = (q-1)//gcd
     56                nthroot = g**q1overn
     57                return [nthroot**a for a in range(gcd)] if all else nthroot
     58        n = n % (q-1)
     59        gcd, alpha, beta = n.xgcd(q-1) # gcd = alpha*n + beta*(p-1), so 1/n = alpha/gcd (mod p-1)
     60        if gcd == 1:
     61            return [self**alpha] if all else self**alpha
     62        n = gcd
     63        self = self**alpha
     64        if cunningham:
     65            F = n._factor_cunningham()
     66        else:
     67            F = n.factor()
     68        from sage.groups.generic import discrete_log
     69        if algorithm is None or algorithm == 'Johnston':
     70            q1overn = (q-1)//n
     71            if self**q1overn != 1:
     72                if all: return []
     73                else: raise ValueError, "no nth root"
     74            g = K.multiplicative_generator()
     75            for r, v in F:
     76                k, h = (q-1).val_unit(r)
     77                z = h * (-h).inverse_mod(r**v)
     78                x = (1 + z) // r**v
     79                if k == 1:
     80                    self = self**x
     81                else:
     82                    t = discrete_log(self**h, g**(r**v*h), r**(k-v), operation='*')
     83                    self = self**x * g**(-z*t)
     84            if all:
     85                nthroot = g**q1overn
     86                L = [self]
     87                for i in range(1,n):
     88                    self *= nthroot
     89                    L.append(self)
     90                return L
     91            else:
     92                return self
     93        else:
     94            raise ValueError, "unknown algorithm"
     95
     96cdef class FinitePolyExtElement(FiniteRingElement):
    3397   
    3498    def _im_gens_(self, codomain, im_gens):
    3599        """
     
    397461
    398462        return order
    399463
     464    def additive_order(self):
     465        """
     466        Return the additive order of this finite field element.
     467
     468        EXAMPLES::
     469       
     470            sage: k.<a> = FiniteField(2^12, 'a')
     471            sage: b = a^3 + a + 1
     472            sage: b.additive_order()
     473            2
     474            sage: k(0).additive_order()
     475            1
     476        """
     477        if self.is_zero():
     478            from sage.rings.integer import Integer
     479            return Integer(1)
     480        return self.parent().characteristic()
     481
    400482    def nth_root(self, n, extend = False, all = False, algorithm=None, cunningham=False):
    401483        r"""
    402         Returns an nth root of self.
     484        Returns an `n`\th root of ``self``.
    403485
    404486        INPUT:
    405487
    406         - ``n`` - integer >= 1
     488        - ``n`` - integer `\geq 1`
    407489
    408         - ``extend`` - bool (default: True); if True, return an nth
     490        - ``extend`` - bool (default: ``False``); if ``True``, return an `n`\th
    409491          root in an extension ring, if necessary. Otherwise, raise a
    410492          ValueError if the root is not in the base ring.  Warning:
    411493          this option is not implemented!
    412494
    413         - ``all`` - bool (default: False); if True, return all nth
    414           roots of self, instead of just one.
     495        - ``all`` - bool (default: ``False``); if ``True``, return all `n`\th
     496          roots of ``self``, instead of just one.
    415497
    416         - ``algorithm`` - string (default: None); 'Johnston' is the only
    417           currently supported option.
     498        - ``algorithm`` - string (default: ``None``); 'Johnston' is the only
     499          currently supported option.  For IntegerMod elements, the problem
     500          is reduced to the prime modulus case using CRT and `p`-adic logs,
     501          and then this algorithm used.
    418502
    419503        OUTPUT:
    420504
    421         If self has an nth root, returns one (if all == False) or a
    422         list of all of them (if all == True).  Otherwise, raises a
    423         ValueError (if extend = False) or a NotImplementedError (if
    424         extend = True).
     505        If self has an `n`\th root, returns one (if ``all`` is ``False``) or a
     506        list of all of them (if ``all`` is ``True``).  Otherwise, raises a
     507        ValueError (if ``extend`` is ``False``) or a ``NotImplementedError`` (if
     508        ``extend`` is ``True``).
    425509
    426510        .. warning::
    427511       
     
    437521            5
    438522            sage: K(23).nth_root(3)
    439523            29
     524
    440525            sage: K.<a> = GF(625)
    441526            sage: (3*a^2+a+1).nth_root(13)**13
    442527            3*a^2 + a + 1
     
    498583            raise NotImplementedError
    499584        from sage.rings.integer import Integer
    500585        n = Integer(n)
    501         return nth_root_common(self, n, all, algorithm, cunningham)
    502 
    503     def additive_order(self):
    504         """
    505         Return the additive order of this finite field element.
    506 
    507         EXAMPLES::
    508        
    509             sage: k.<a> = FiniteField(2^12, 'a')
    510             sage: b = a^3 + a + 1
    511             sage: b.additive_order()
    512             2
    513             sage: k(0).additive_order()
    514             1
    515         """
    516         if self.is_zero():
    517             from sage.rings.integer import Integer
    518             return Integer(1)
    519         return self.parent().characteristic()
     586        return self._nth_root_common(n, all, algorithm, cunningham)
    520587
    521588    def pth_power(self, int k = 1):
    522589        """
     
    574641        """
    575642        return self.pth_power(-k)
    576643
    577 def nth_root_common(self, n, all, algorithm, cunningham):
    578     """
    579     This function exists to reduce code duplication between finite field nth roots and integer_mod nth roots.
    580 
    581     The inputs are described there.
    582 
    583     TESTS::
    584 
    585         sage: a = Zmod(17)(13)
    586         sage: from sage.rings.finite_rings.element_base import nth_root_common
    587         sage: nth_root_common(a, 4, True, "Johnston", False)
    588         [3, 5, 14, 12]
    589     """
    590     K = self.parent()
    591     q = K.order()
    592     if self.is_one():
    593         gcd = n.gcd(q-1)
    594         if gcd == 1:
    595             if all: return [self]
    596             else: return self
    597         else:
    598             # the following may eventually be improved to not need a multiplicative generator.
    599             g = K.multiplicative_generator()
    600             q1overn = (q-1)//gcd
    601             nthroot = g**q1overn
    602             return [nthroot**a for a in range(gcd)] if all else nthroot
    603     n = n % (q-1)
    604     gcd, alpha, beta = n.xgcd(q-1) # gcd = alpha*n + beta*(p-1), so 1/n = alpha/gcd (mod p-1)
    605     if gcd == 1:
    606         return [self**alpha] if all else self**alpha
    607     n = gcd
    608     self = self**alpha
    609     if cunningham:
    610         F = n._factor_cunningham()
    611     else:
    612         F = n.factor()
    613     from sage.groups.generic import discrete_log
    614     if algorithm is None or algorithm == 'Johnston':
    615         q1overn = (q-1)//n
    616         if self**q1overn != 1:
    617             if all: return []
    618             else: raise ValueError, "no nth root"
    619         g = K.multiplicative_generator()
    620         for r, v in F:
    621             k, h = (q-1).val_unit(r)
    622             z = h * (-h).inverse_mod(r**v)
    623             x = (1 + z) // r**v
    624             if k == 1:
    625                 self = self**x
    626             else:
    627                 t = discrete_log(self**h, g**(r**v*h), r**(k-v), operation='*')
    628                 self = self**x * g**(-z*t)
    629         if all:
    630             nthroot = g**q1overn
    631             L = [self]
    632             for i in range(1,n):
    633                 self *= nthroot
    634                 L.append(self)
    635             return L
    636         else:
    637             return self
    638     else:
    639         raise ValueError, "unknown algorithm"
  • sage/rings/finite_rings/element_ext_pari.py

    diff -r 6d6c6a580546 -r 52506cc26942 sage/rings/finite_rings/element_ext_pari.py
    a b  
    3434from sage.rings.integer import Integer
    3535import sage.rings.rational as rational
    3636from sage.libs.pari.all import pari, pari_gen
    37 from sage.rings.finite_rings.element_base import FiniteFieldElement
     37from sage.rings.finite_rings.element_base import FinitePolyExtElement
    3838import sage.rings.field_element as field_element
    3939import sage.rings.finite_rings.integer_mod as integer_mod
    4040from element_base import is_FiniteFieldElement
     
    4242from sage.structure.dynamic_class import dynamic_class
    4343from sage.categories.finite_fields import FiniteFields
    4444
    45 class FiniteField_ext_pariElement(FiniteFieldElement):
     45class FiniteField_ext_pariElement(FinitePolyExtElement):
    4646    """
    4747    An element of a finite field.
    4848   
  • sage/rings/finite_rings/element_givaro.pxd

    diff -r 6d6c6a580546 -r 52506cc26942 sage/rings/finite_rings/element_givaro.pxd
    a b  
    11from sage.structure.element cimport Element, RingElement, ModuleElement
    2 from sage.rings.finite_rings.element_base cimport FiniteFieldElement
     2from sage.rings.finite_rings.element_base cimport FinitePolyExtElement
    33
    44from sage.structure.parent  cimport Parent
    55from sage.structure.sage_object cimport SageObject
     
    6161    void delete "delete "(void *o)
    6262    int gfq_element_factory "GFqDom<int>::Element"()
    6363
    64 cdef class FiniteField_givaroElement(FiniteFieldElement) #forward declaration
     64cdef class FiniteField_givaroElement(FinitePolyExtElement) #forward declaration
    6565
    6666cdef class Cache_givaro(SageObject):
    6767    cdef GivaroGfq *objectptr # C++ object
     
    8383    cdef int iterator
    8484    cdef Cache_givaro _cache
    8585
    86 cdef class FiniteField_givaroElement(FiniteFieldElement):
     86cdef class FiniteField_givaroElement(FinitePolyExtElement):
    8787    cdef int element
    8888    cdef Cache_givaro _cache
    8989    cdef object _multiplicative_order
  • sage/rings/finite_rings/element_givaro.pyx

    diff -r 6d6c6a580546 -r 52506cc26942 sage/rings/finite_rings/element_givaro.pyx
    a b  
    462462            pass # handle this in next if clause
    463463
    464464        elif PY_TYPE_CHECK(e,FiniteField_ext_pariElement):
    465             # reduce FiniteFieldElements to pari
     465            # reduce FiniteField_ext_pariElements to pari
    466466            e = e._pari_()
    467467
    468468        elif sage.interfaces.gap.is_GapElement(e):
     
    848848        """
    849849        return self
    850850
    851 cdef class FiniteField_givaroElement(FiniteFieldElement):
     851cdef class FiniteField_givaroElement(FinitePolyExtElement):
    852852    """
    853853    An element of a (Givaro) finite field.
    854854    """
     
    877877            0
    878878           
    879879        """
    880         FiniteFieldElement.__init__(self, parent)
     880        FinitePolyExtElement.__init__(self, parent)
    881881        self._cache = parent._cache
    882882        self.element = 0
    883883       
  • sage/rings/finite_rings/element_ntl_gf2e.pxd

    diff -r 6d6c6a580546 -r 52506cc26942 sage/rings/finite_rings/element_ntl_gf2e.pxd
    a b  
    22
    33from sage.rings.finite_rings.finite_field_base cimport FiniteField
    44from sage.structure.element cimport Element, RingElement, ModuleElement
    5 from sage.rings.finite_rings.element_base cimport FiniteFieldElement
     5from sage.rings.finite_rings.element_base cimport FinitePolyExtElement
    66
    7 cdef class FiniteField_ntl_gf2eElement(FiniteFieldElement)
     7cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement)
    88
    99cdef class FiniteField_ntl_gf2e(FiniteField):
    1010    cdef GF2EContext_c F
     
    1919    cdef int iterator
    2020    cdef FiniteField_ntl_gf2e _parent
    2121
    22 cdef class FiniteField_ntl_gf2eElement(FiniteFieldElement):
     22cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement):
    2323    cdef GF2E_c x
    2424    cdef FiniteField_ntl_gf2eElement _new(FiniteField_ntl_gf2eElement self)
  • sage/rings/finite_rings/element_ntl_gf2e.pyx

    diff -r 6d6c6a580546 -r 52506cc26942 sage/rings/finite_rings/element_ntl_gf2e.pyx
    a b  
    482482            pass # handle this in next if clause
    483483
    484484        elif PY_TYPE_CHECK(e,FiniteField_ext_pariElement):
    485             # reduce FiniteFieldElements to pari
     485            # reduce FiniteField_ext_pariElements to pari
    486486            e = e._pari_()
    487487
    488488        elif is_GapElement(e):
     
    728728        f = pari(str(self.modulus()))
    729729        return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())
    730730       
    731 cdef class FiniteField_ntl_gf2eElement(FiniteFieldElement):
     731cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement):
    732732    """
    733733    An element of an NTL:GF2E finite field.
    734734    """
  • sage/rings/finite_rings/integer_mod.pxd

    diff -r 6d6c6a580546 -r 52506cc26942 sage/rings/finite_rings/integer_mod.pxd
    a b  
    88    int_fast32_t INTEGER_MOD_INT32_LIMIT
    99    int_fast64_t INTEGER_MOD_INT64_LIMIT
    1010
    11 cimport sage.structure.element
     11from sage.rings.finite_rings.element_base cimport FiniteRingElement
    1212from sage.rings.integer cimport Integer
    1313
    1414cdef class NativeIntStruct:
     
    1919    cdef object inverses # also a list
    2020    cdef lookup(NativeIntStruct self, Py_ssize_t value)
    2121
    22 cdef class IntegerMod_abstract(sage.structure.element.CommutativeRingElement):
     22cdef class IntegerMod_abstract(FiniteRingElement):
    2323    cdef NativeIntStruct __modulus
    2424    cdef _new_c_from_long(self, long value)
    2525    cdef void set_from_mpz(self, mpz_t value)
  • sage/rings/finite_rings/integer_mod.pyx

    diff -r 6d6c6a580546 -r 52506cc26942 sage/rings/finite_rings/integer_mod.pyx
    a b  
    257257        return <object>PyList_GET_ITEM(self.table, value)
    258258
    259259   
    260 cdef class IntegerMod_abstract(sage.structure.element.CommutativeRingElement):
     260cdef class IntegerMod_abstract(FiniteRingElement):
    261261
    262262    def __init__(self, parent):
    263263        """
     
    11451145                return ans
    11461146            else:
    11471147                return sign[0] * K(R.teichmuller(modp) * (plog // n).exp())
    1148         from element_base import nth_root_common
    1149         return nth_root_common(self, n, all, algorithm, cunningham)
     1148        return self._nth_root_common(n, all, algorithm, cunningham)
    11501149       
    11511150    def _balanced_abs(self):
    11521151        """