コード例 #1
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError, "Unknown representation %s" % repr

        q = Integer(q)
        if q < 2:
            raise ValueError, "q  must be a prime power"
        F = q.factor()
        if len(F) > 1:
            raise ValueError, "q must be a prime power"
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError, "q must be < 2^16"

        import constructor
        FiniteField.__init__(self,
                             constructor.FiniteField(p),
                             name,
                             normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        self._is_conway = False
        if modulus is None or modulus == 'conway':
            if k == 1:
                modulus = 'random'  # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.constructor import conway_polynomial
                modulus = conway_polynomial(p, k)
                self._is_conway = True
            elif modulus is None:
                modulus = 'random'
            else:
                raise ValueError, "Conway polynomial not found"

        from sage.rings.polynomial.all import is_Polynomial
        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
コード例 #2
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s" % repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError("q must be < 2^16")

        from .finite_field_constructor import GF
        FiniteField.__init__(self, GF(p), name, normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            from sage.misc.superseded import deprecation
            deprecation(
                16930,
                "constructing a FiniteField_givaro without giving a polynomial as modulus is deprecated, use the more general FiniteField constructor instead"
            )
            R = GF(p)['x']
            if modulus is None or isinstance(modulus, str):
                modulus = R.irreducible_element(k, algorithm=modulus)
            else:
                modulus = R(modulus)

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
        self._modulus = modulus
コード例 #3
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ["int", "log", "poly"]:
            raise ValueError, "Unknown representation %s" % repr

        q = Integer(q)
        if q < 2:
            raise ValueError, "q  must be a prime power"
        F = q.factor()
        if len(F) > 1:
            raise ValueError, "q must be a prime power"
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError, "q must be < 2^16"

        import constructor

        FiniteField.__init__(self, constructor.FiniteField(p), name, normalize=False)

        self._kwargs["repr"] = repr
        self._kwargs["cache"] = cache

        self._is_conway = False
        if modulus is None or modulus == "conway":
            if k == 1:
                modulus = "random"  # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.constructor import conway_polynomial

                modulus = conway_polynomial(p, k)
                self._is_conway = True
            elif modulus is None:
                modulus = "random"
            else:
                raise ValueError, "Conway polynomial not found"

        from sage.rings.polynomial.all import is_Polynomial

        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
コード例 #4
0
ファイル: finite_field_givaro.py プロジェクト: novoselt/sage
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ["int", "log", "poly"]:
            raise ValueError("Unknown representation %s" % repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError("q must be < 2^16")

        from .finite_field_constructor import GF

        FiniteField.__init__(self, GF(p), name, normalize=False)

        self._kwargs["repr"] = repr
        self._kwargs["cache"] = cache

        from sage.rings.polynomial.polynomial_element import is_Polynomial

        if not is_Polynomial(modulus):
            from sage.misc.superseded import deprecation

            deprecation(
                16930,
                "constructing a FiniteField_givaro without giving a polynomial as modulus is deprecated, use the more general FiniteField constructor instead",
            )
            R = GF(p)["x"]
            if modulus is None or isinstance(modulus, str):
                modulus = R.irreducible_element(k, algorithm=modulus)
            else:
                modulus = R(modulus)

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
        self._modulus = modulus
コード例 #5
0
ファイル: finite_field_givaro.py プロジェクト: Etn40ff/sage
    def __init__(self, q, name="a",  modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s"%repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q  must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1<<16:
            raise ValueError("q must be < 2^16")

        import constructor
        FiniteField.__init__(self, constructor.FiniteField(p), name, normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        if modulus is None or modulus == 'conway':
            if k == 1:
                modulus = 'random' # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.conway_polynomials import conway_polynomial
                modulus = conway_polynomial(p, k)
            elif modulus is None:
                modulus = 'random'
            else:
                raise ValueError("Conway polynomial not found")

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
コード例 #6
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s"%repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1<<16:
            raise ValueError("q must be < 2^16")

        from .finite_field_constructor import GF
        FiniteField.__init__(self, GF(p), name, normalize=False)

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            raise TypeError("modulus must be a polynomial")

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
        self._modulus = modulus
コード例 #7
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s"%repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1<<16:
            raise ValueError("q must be < 2^16")

        from .finite_field_constructor import GF
        FiniteField.__init__(self, GF(p), name, normalize=False)

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            raise TypeError("modulus must be a polynomial")

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
        self._modulus = modulus
コード例 #8
0
ファイル: finite_field_givaro.py プロジェクト: bukzor/sage
class FiniteField_givaro(FiniteField):
    """
    Finite field implemented using Zech logs and the cardinality must be
    less than `2^{16}`. By default, conway polynomials are used as minimal
    polynomials.

    INPUT:

    - ``q`` -- `p^n` (must be prime power)

    - ``name`` -- (default: ``'a'``) variable used for
      :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.poly_repr()`

    - ``modulus`` -- A minimal polynomial to use for reduction.

    - ``repr`` -- (default: ``'poly'``) controls the way elements are printed
      to the user:

      - 'log': repr is
        :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.log_repr()`
      - 'int': repr is
        :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.int_repr()`
      - 'poly': repr is
        :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.poly_repr()`

    - cache -- (default: ``False``) if ``True`` a cache of all elements of
      this field is created. Thus, arithmetic does not create new elements
      which speeds calculations up. Also, if many elements are needed during a
      calculation this cache reduces the memory requirement as at most
      :meth:`order` elements are created.

    OUTPUT:

    Givaro finite field with characteristic `p` and cardinality `p^n`.

    EXAMPLES:

    By default conway polynomials are used for extension fields::

        sage: k.<a> = GF(2**8)
        sage: -a ^ k.degree()
        a^4 + a^3 + a^2 + 1
        sage: f = k.modulus(); f
        x^8 + x^4 + x^3 + x^2 + 1

    You may enforce a modulus::

        sage: P.<x> = PolynomialRing(GF(2))
        sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael Polynomial
        sage: k.<a> = GF(2^8, modulus=f)
        sage: k.modulus()
        x^8 + x^4 + x^3 + x + 1
        sage: a^(2^8)
        a

    You may enforce a random modulus::

        sage: k = GF(3**5, 'a', modulus='random')
        sage: k.modulus() # random polynomial
        x^5 + 2*x^4 + 2*x^3 + x^2 + 2

    Three different representations are possible::

        sage: FiniteField(9, 'a', impl='givaro', repr='poly').gen()
        a
        sage: FiniteField(9, 'a', impl='givaro', repr='int').gen()
        3
        sage: FiniteField(9, 'a', impl='givaro', repr='log').gen()
        1

    For prime fields, the default modulus is the polynomial `x - 1`,
    but you can ask for a different modulus::

        sage: GF(1009, impl='givaro').modulus()
        x + 1008
        sage: GF(1009, impl='givaro', modulus='conway').modulus()
        x + 998
    """
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s"%repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1<<16:
            raise ValueError("q must be < 2^16")

        from constructor import GF
        FiniteField.__init__(self, GF(p), name, normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            from sage.misc.superseded import deprecation
            deprecation(16930, "constructing a FiniteField_givaro without giving a polynomial as modulus is deprecated, use the more general FiniteField constructor instead")
            R = GF(p)['x']
            if modulus is None or isinstance(modulus, str):
                modulus = R.irreducible_element(k, algorithm=modulus)
            else:
                modulus = R(modulus)

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
        self._modulus = modulus

    def characteristic(self):
        """
        Return the characteristic of this field.

        EXAMPLES::

            sage: p = GF(19^5,'a').characteristic(); p
            19
            sage: type(p)
            <type 'sage.rings.integer.Integer'>
        """
        return Integer(self._cache.characteristic())

    def order(self):
        """
        Return the cardinality of this field.

        OUTPUT:

        Integer -- the number of elements in ``self``.

        EXAMPLES::

            sage: n = GF(19^5,'a').order(); n
            2476099
            sage: type(n)
            <type 'sage.rings.integer.Integer'>
        """
        return self._cache.order()

    def degree(self):
        r"""
        If the cardinality of ``self`` is `p^n`, then this returns `n`.

        OUTPUT:

        Integer -- the degree

        EXAMPLES::

            sage: GF(3^4,'a').degree()
            4
        """
        return Integer(self._cache.exponent())

    def _repr_option(self, key):
        """
        Metadata about the :meth:`_repr_` output.

        See :meth:`sage.structure.parent._repr_option` for details.

        EXAMPLES::

            sage: GF(23**3, 'a', repr='log')._repr_option('element_is_atomic')
            True
            sage: GF(23**3, 'a', repr='int')._repr_option('element_is_atomic')
            True
            sage: GF(23**3, 'a', repr='poly')._repr_option('element_is_atomic')
            False
        """
        if key == 'element_is_atomic':
            return self._cache.repr != 0   # 0 means repr='poly'
        return super(FiniteField_givaro, self)._repr_option(key)

    def random_element(self, *args, **kwds):
        """
        Return a random element of ``self``.

        EXAMPLES::

            sage: k = GF(23**3, 'a')
            sage: e = k.random_element(); e
            2*a^2 + 14*a + 21
            sage: type(e)
            <type 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>

            sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))
            sage: P.random_element(5)
            2*a + 2 + (a^2 + a + 2)*x + (2*a + 1)*x^2 + (2*a^2 + a)*x^3 + 2*a^2*x^4 + O(x^5)
        """
        return self._cache.random_element()

    def _element_constructor_(self, e):
        """
        Coerces several data types to ``self``.

        INPUT:

        - ``e`` -- data to coerce

        EXAMPLES:

        :class:`FiniteField_givaroElement` are accepted where the parent
        is either ``self``, equals ``self`` or is the prime subfield::

            sage: k = GF(2**8, 'a')
            sage: k.gen() == k(k.gen())
            True

        Floats, ints, longs, Integer are interpreted modulo characteristic::

            sage: k(2) # indirect doctest
            0

            Floats coerce in:
            sage: k(float(2.0))
            0

        Rational are interpreted as ``self(numerator)/self(denominator)``.
        Both may not be greater than :meth:characteristic()`.
        ::

            sage: k = GF(3**8, 'a')
            sage: k(1/2) == k(1)/k(2)
            True

        Free module elements over :meth:`prime_subfield()` are interpreted
        'little endian'::

            sage: k = GF(2**8, 'a')
            sage: e = k.vector_space().gen(1); e
            (0, 1, 0, 0, 0, 0, 0, 0)
            sage: k(e)
            a

        ``None`` yields zero::

            sage: k(None)
            0

        Strings are evaluated as polynomial representation of elements in
        ``self``::

            sage: k('a^2+1')
            a^2 + 1

        Univariate polynomials coerce into finite fields by evaluating
        the polynomial at the field's generator::

            sage: R.<x> = QQ[]
            sage: k, a = FiniteField(5^2, 'a', impl='givaro').objgen()
            sage: k(R(2/3))
            4
            sage: k(x^2)
            a + 3
            sage: R.<x> = GF(5)[]
            sage: k(x^3-2*x+1)
            2*a + 4

            sage: x = polygen(QQ)
            sage: k(x^25)
            a

            sage: Q, q = FiniteField(5^3, 'q', impl='givaro').objgen()
            sage: L = GF(5)
            sage: LL.<xx> = L[]
            sage: Q(xx^2 + 2*xx + 4)
            q^2 + 2*q + 4

        Multivariate polynomials only coerce if constant::

            sage: R = k['x,y,z']; R
            Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2
            sage: k(R(2))
            2
            sage: R = QQ['x,y,z']
            sage: k(R(1/5))
            Traceback (most recent call last):
            ...
            ZeroDivisionError: division by zero in finite field.

        PARI elements are interpreted as finite field elements; this PARI
        flexibility is (absurdly!) liberal::

            sage: k = GF(2**8, 'a')
            sage: k(pari('Mod(1,2)'))
            1
            sage: k(pari('Mod(2,3)'))
            0
            sage: k(pari('Mod(1,3)*a^20'))
            a^7 + a^5 + a^4 + a^2

        We can coerce from PARI finite field implementations::

            sage: K.<a> = GF(3^10, impl="givaro")
            sage: a^20
            2*a^9 + 2*a^8 + a^7 + 2*a^5 + 2*a^4 + 2*a^3 + 1
            sage: M.<c> = GF(3^10, impl="pari_ffelt")
            sage: K(c^20)
            2*a^9 + 2*a^8 + a^7 + 2*a^5 + 2*a^4 + 2*a^3 + 1

        GAP elements need to be finite field elements::

            sage: x = gap('Z(13)')
            sage: F = FiniteField(13, impl='givaro')
            sage: F(x)
            2
            sage: F(gap('0*Z(13)'))
            0
            sage: F = FiniteField(13^2, 'a', impl='givaro')
            sage: x = gap('Z(13)')
            sage: F(x)
            2
            sage: x = gap('Z(13^2)^3')
            sage: F(x)
            12*a + 11
            sage: F.multiplicative_generator()^3
            12*a + 11

            sage: k.<a> = GF(29^3)
            sage: k(48771/1225)
            28

            sage: F9 = FiniteField(9, impl='givaro', conway=True, prefix='a')
            sage: F81 = FiniteField(81, impl='givaro', conway=True, prefix='a')
            sage: F81(F9.gen())
            2*a4^3 + 2*a4^2 + 1
        """
        return self._cache.element_from_data(e)

    def gen(self, n=0):
        r"""
        Return a generator of ``self`` over its prime field, which is a
        root of ``self.modulus()``.

        INPUT:

        - ``n`` -- must be 0

        OUTPUT:

        An element `a` of ``self`` such that ``self.modulus()(a) == 0``.

        .. WARNING::

            This generator is not guaranteed to be a generator for the
            multiplicative group.  To obtain the latter, use
            :meth:`~sage.rings.finite_rings.finite_field_base.FiniteFields.multiplicative_generator()`
            or use the ``modulus="primitive"`` option when constructing
            the field.

        EXAMPLES::

            sage: k = GF(3^4, 'b'); k.gen()
            b
            sage: k.gen(1)
            Traceback (most recent call last):
            ...
            IndexError: only one generator
            sage: F = FiniteField(31, impl='givaro')
            sage: F.gen()
            1
        """
        if n:
            raise IndexError("only one generator")
        return self._cache.gen()

    def prime_subfield(self):
        r"""
        Return the prime subfield `\GF{p}` of self if ``self`` is `\GF{p^n}`.

        EXAMPLES::

            sage: GF(3^4, 'b').prime_subfield()
            Finite Field of size 3

            sage: S.<b> = GF(5^2); S
            Finite Field in b of size 5^2
            sage: S.prime_subfield()
            Finite Field of size 5
            sage: type(S.prime_subfield())
            <class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>
        """
        try:
            return self._prime_subfield
        except AttributeError:
            from constructor import GF
            self._prime_subfield = GF(self.characteristic())
            return self._prime_subfield

    def log_to_int(self, n):
        r"""
        Given an integer `n` this method returns ``i`` where ``i``
        satisfies `g^n = i` where `g` is the generator of ``self``; the
        result is interpreted as an integer.

        INPUT:

        - ``n`` -- log representation of a finite field element

        OUTPUT:

        integer representation of a finite field element.

        EXAMPLES::

            sage: k = GF(2**8, 'a')
            sage: k.log_to_int(4)
            16
            sage: k.log_to_int(20)
            180
        """
        return self._cache.log_to_int(n)

    def int_to_log(self, n):
        r"""
        Given an integer `n` this method returns `i` where `i` satisfies
        `g^i = n \mod p` where `g` is the generator and `p` is the
        characteristic of ``self``.

        INPUT:

        - ``n`` -- integer representation of an finite field element

        OUTPUT:

        log representation of ``n``

        EXAMPLES::

            sage: k = GF(7**3, 'a')
            sage: k.int_to_log(4)
            228
            sage: k.int_to_log(3)
            57
            sage: k.gen()^57
            3
        """
        return self._cache.int_to_log(n)

    def fetch_int(self, n):
        r"""
        Given an integer `n` return a finite field element in ``self``
        which equals `n` under the condition that :meth:`gen()` is set to
        :meth:`characteristic()`.

        EXAMPLES::

            sage: k.<a> = GF(2^8)
            sage: k.fetch_int(8)
            a^3
            sage: e = k.fetch_int(151); e
            a^7 + a^4 + a^2 + a + 1
            sage: 2^7 + 2^4 + 2^2 + 2 + 1
            151
        """
        return self._cache.fetch_int(n)

    def _pari_modulus(self):
        """
        Return the modulus of ``self`` in a format for PARI.

        EXAMPLES::

            sage: GF(3^4,'a')._pari_modulus()
            Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(2, 3)
        """
        f = pari(str(self.modulus()))
        return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())

    def __iter__(self):
        """
        Finite fields may be iterated over.

        EXAMPLES::

            sage: list(GF(2**2, 'a'))
            [0, a, a + 1, 1]
        """
        from element_givaro import FiniteField_givaro_iterator
        return FiniteField_givaro_iterator(self._cache)

    def a_times_b_plus_c(self, a, b, c):
        """
        Return ``a*b + c``. This is faster than multiplying ``a`` and ``b``
        first and adding ``c`` to the result.

        INPUT:

        - ``a,b,c`` -- :class:`~~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`

        EXAMPLES::

            sage: k.<a> = GF(2**8)
            sage: k.a_times_b_plus_c(a,a,k(1))
            a^2 + 1
        """
        return self._cache.a_times_b_plus_c(a, b, c)

    def a_times_b_minus_c(self, a, b, c):
        """
        Return ``a*b - c``.

        INPUT:

        - ``a,b,c`` -- :class:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`

        EXAMPLES::

            sage: k.<a> = GF(3**3)
            sage: k.a_times_b_minus_c(a,a,k(1))
            a^2 + 2
        """
        return self._cache.a_times_b_minus_c(a, b, c)

    def c_minus_a_times_b(self, a, b, c):
        """
        Return ``c - a*b``.

        INPUT:

        - ``a,b,c`` -- :class:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`

        EXAMPLES::

            sage: k.<a> = GF(3**3)
            sage: k.c_minus_a_times_b(a,a,k(1))
            2*a^2 + 1
        """
        return self._cache.c_minus_a_times_b(a, b, c)

    def frobenius_endomorphism(self, n=1):
        """
        INPUT:

        -  ``n`` -- an integer (default: 1)

        OUTPUT:

        The `n`-th power of the absolute arithmetic Frobenius
        endomorphism on this finite field.

        EXAMPLES::

            sage: k.<t> = GF(3^5)
            sage: Frob = k.frobenius_endomorphism(); Frob
            Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5

            sage: a = k.random_element()
            sage: Frob(a) == a^3
            True

        We can specify a power::

            sage: k.frobenius_endomorphism(2)
            Frobenius endomorphism t |--> t^(3^2) on Finite Field in t of size 3^5

        The result is simplified if possible::

            sage: k.frobenius_endomorphism(6)
            Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5
            sage: k.frobenius_endomorphism(5)
            Identity endomorphism of Finite Field in t of size 3^5

        Comparisons work::

            sage: k.frobenius_endomorphism(6) == Frob
            True
            sage: from sage.categories.morphism import IdentityMorphism
            sage: k.frobenius_endomorphism(5) == IdentityMorphism(k)
            True

        AUTHOR:

        - Xavier Caruso (2012-06-29)
        """
        from sage.rings.finite_rings.hom_finite_field_givaro import FrobeniusEndomorphism_givaro
        return FrobeniusEndomorphism_givaro(self, n)
コード例 #9
0
class FiniteField_givaro(FiniteField):
    """
    Finite field implemented using Zech logs and the cardinality must be
    less than `2^{16}`. By default, Conway polynomials are used as minimal
    polynomials.

    INPUT:

    - ``q`` -- `p^n` (must be prime power)

    - ``name`` -- (default: ``'a'``) variable used for
      :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.poly_repr()`

    - ``modulus`` -- A minimal polynomial to use for reduction.

    - ``repr`` -- (default: ``'poly'``) controls the way elements are printed
      to the user:

      - 'log': repr is
        :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.log_repr()`
      - 'int': repr is
        :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.int_repr()`
      - 'poly': repr is
        :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.poly_repr()`

    - cache -- (default: ``False``) if ``True`` a cache of all elements of
      this field is created. Thus, arithmetic does not create new elements
      which speeds calculations up. Also, if many elements are needed during a
      calculation this cache reduces the memory requirement as at most
      :meth:`order` elements are created.

    OUTPUT:

    Givaro finite field with characteristic `p` and cardinality `p^n`.

    EXAMPLES:

    By default, Conway polynomials are used for extension fields::

        sage: k.<a> = GF(2**8)
        sage: -a ^ k.degree()
        a^4 + a^3 + a^2 + 1
        sage: f = k.modulus(); f
        x^8 + x^4 + x^3 + x^2 + 1

    You may enforce a modulus::

        sage: P.<x> = PolynomialRing(GF(2))
        sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael Polynomial
        sage: k.<a> = GF(2^8, modulus=f)
        sage: k.modulus()
        x^8 + x^4 + x^3 + x + 1
        sage: a^(2^8)
        a

    You may enforce a random modulus::

        sage: k = GF(3**5, 'a', modulus='random')
        sage: k.modulus() # random polynomial
        x^5 + 2*x^4 + 2*x^3 + x^2 + 2

    Three different representations are possible::

        sage: FiniteField(9, 'a', impl='givaro', repr='poly').gen()
        a
        sage: FiniteField(9, 'a', impl='givaro', repr='int').gen()
        3
        sage: FiniteField(9, 'a', impl='givaro', repr='log').gen()
        1

    For prime fields, the default modulus is the polynomial `x - 1`,
    but you can ask for a different modulus::

        sage: GF(1009, impl='givaro').modulus()
        x + 1008
        sage: GF(1009, impl='givaro', modulus='conway').modulus()
        x + 998
    """
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s"%repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1<<16:
            raise ValueError("q must be < 2^16")

        from .finite_field_constructor import GF
        FiniteField.__init__(self, GF(p), name, normalize=False)

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            raise TypeError("modulus must be a polynomial")

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
        self._modulus = modulus

    def characteristic(self):
        """
        Return the characteristic of this field.

        EXAMPLES::

            sage: p = GF(19^5,'a').characteristic(); p
            19
            sage: type(p)
            <type 'sage.rings.integer.Integer'>
        """
        return Integer(self._cache.characteristic())

    def order(self):
        """
        Return the cardinality of this field.

        OUTPUT:

        Integer -- the number of elements in ``self``.

        EXAMPLES::

            sage: n = GF(19^5,'a').order(); n
            2476099
            sage: type(n)
            <type 'sage.rings.integer.Integer'>
        """
        return self._cache.order()

    def degree(self):
        r"""
        If the cardinality of ``self`` is `p^n`, then this returns `n`.

        OUTPUT:

        Integer -- the degree

        EXAMPLES::

            sage: GF(3^4,'a').degree()
            4
        """
        return Integer(self._cache.exponent())

    def _repr_option(self, key):
        """
        Metadata about the :meth:`_repr_` output.

        See :meth:`sage.structure.parent._repr_option` for details.

        EXAMPLES::

            sage: GF(23**3, 'a', repr='log')._repr_option('element_is_atomic')
            True
            sage: GF(23**3, 'a', repr='int')._repr_option('element_is_atomic')
            True
            sage: GF(23**3, 'a', repr='poly')._repr_option('element_is_atomic')
            False
        """
        if key == 'element_is_atomic':
            return self._cache.repr != 0   # 0 means repr='poly'
        return super(FiniteField_givaro, self)._repr_option(key)

    def random_element(self, *args, **kwds):
        """
        Return a random element of ``self``.

        EXAMPLES::

            sage: k = GF(23**3, 'a')
            sage: e = k.random_element(); e
            2*a^2 + 14*a + 21
            sage: type(e)
            <type 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>

            sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))
            sage: P.random_element(5)
            a^2 + (2*a^2 + a)*x + x^2 + (2*a^2 + 2*a + 2)*x^3 + (a^2 + 2*a + 2)*x^4 + O(x^5)
        """
        return self._cache.random_element()

    def _element_constructor_(self, e):
        """
        Coerces several data types to ``self``.

        INPUT:

        - ``e`` -- data to coerce

        EXAMPLES:

        :class:`FiniteField_givaroElement` are accepted where the parent
        is either ``self``, equals ``self`` or is the prime subfield::

            sage: k = GF(2**8, 'a')
            sage: k.gen() == k(k.gen())
            True

        Floats, ints, longs, Integer are interpreted modulo characteristic::

            sage: k(2) # indirect doctest
            0

        Floats are converted like integers::

            sage: k(float(2.0))
            0

        Rational are interpreted as ``self(numerator)/self(denominator)``.
        Both may not be greater than :meth:`characteristic`.
        ::

            sage: k = GF(3**8, 'a')
            sage: k(1/2) == k(1)/k(2)
            True

        Free module elements over :meth:`prime_subfield()` are interpreted
        'little endian'::

            sage: k = GF(2**8, 'a')
            sage: e = k.vector_space(map=False).gen(1); e
            (0, 1, 0, 0, 0, 0, 0, 0)
            sage: k(e)
            a

        ``None`` yields zero::

            sage: k(None)
            0

        Strings are evaluated as polynomial representation of elements in
        ``self``::

            sage: k('a^2+1')
            a^2 + 1

        Univariate polynomials coerce into finite fields by evaluating
        the polynomial at the field's generator::

            sage: R.<x> = QQ[]
            sage: k.<a> = FiniteField(5^2, 'a', impl='givaro')
            sage: k(R(2/3))
            4
            sage: k(x^2)
            a + 3
            sage: R.<x> = GF(5)[]
            sage: k(x^3-2*x+1)
            2*a + 4

            sage: x = polygen(QQ)
            sage: k(x^25)
            a

            sage: Q.<q> = FiniteField(5^3, 'q', impl='givaro')
            sage: L = GF(5)
            sage: LL.<xx> = L[]
            sage: Q(xx^2 + 2*xx + 4)
            q^2 + 2*q + 4

        Multivariate polynomials only coerce if constant::

            sage: R = k['x,y,z']; R
            Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2
            sage: k(R(2))
            2
            sage: R = QQ['x,y,z']
            sage: k(R(1/5))
            Traceback (most recent call last):
            ...
            ZeroDivisionError: division by zero in finite field

        PARI elements are interpreted as finite field elements; this PARI
        flexibility is (absurdly!) liberal::

            sage: k.<a> = GF(2^8)
            sage: k(pari('Mod(1,2)'))
            1
            sage: k(pari('Mod(2,3)'))
            a
            sage: k(pari('Mod(1,3)*a^20'))
            a^7 + a^5 + a^4 + a^2
            sage: k(pari('O(x)'))
            Traceback (most recent call last):
            ...
            TypeError: unable to convert PARI t_SER to Finite Field in a of size 2^8

        We can coerce from PARI finite field implementations::

            sage: K.<a> = GF(3^10, impl="givaro")
            sage: a^20
            2*a^9 + 2*a^8 + a^7 + 2*a^5 + 2*a^4 + 2*a^3 + 1
            sage: M.<c> = GF(3^10, impl="pari_ffelt")
            sage: K(c^20)
            2*a^9 + 2*a^8 + a^7 + 2*a^5 + 2*a^4 + 2*a^3 + 1

        GAP elements need to be finite field elements::

            sage: x = gap('Z(13)')
            sage: F = FiniteField(13, impl='givaro')
            sage: F(x)
            2
            sage: F(gap('0*Z(13)'))
            0
            sage: F = FiniteField(13^2, 'a', impl='givaro')
            sage: x = gap('Z(13)')
            sage: F(x)
            2
            sage: x = gap('Z(13^2)^3')
            sage: F(x)
            12*a + 11
            sage: F.multiplicative_generator()^3
            12*a + 11

            sage: k.<a> = GF(29^3)
            sage: k(48771/1225)
            28

            sage: F9 = FiniteField(9, impl='givaro', prefix='a')
            sage: F81 = FiniteField(81, impl='givaro', prefix='a')
            sage: F81(F9.gen())
            2*a4^3 + 2*a4^2 + 1
        """
        return self._cache.element_from_data(e)

    def gen(self, n=0):
        r"""
        Return a generator of ``self`` over its prime field, which is a
        root of ``self.modulus()``.

        INPUT:

        - ``n`` -- must be 0

        OUTPUT:

        An element `a` of ``self`` such that ``self.modulus()(a) == 0``.

        .. WARNING::

            This generator is not guaranteed to be a generator for the
            multiplicative group.  To obtain the latter, use
            :meth:`~sage.rings.finite_rings.finite_field_base.FiniteFields.multiplicative_generator()`
            or use the ``modulus="primitive"`` option when constructing
            the field.

        EXAMPLES::

            sage: k = GF(3^4, 'b'); k.gen()
            b
            sage: k.gen(1)
            Traceback (most recent call last):
            ...
            IndexError: only one generator
            sage: F = FiniteField(31, impl='givaro')
            sage: F.gen()
            1
        """
        if n:
            raise IndexError("only one generator")
        return self._cache.gen()

    def prime_subfield(self):
        r"""
        Return the prime subfield `\GF{p}` of self if ``self`` is `\GF{p^n}`.

        EXAMPLES::

            sage: GF(3^4, 'b').prime_subfield()
            Finite Field of size 3

            sage: S.<b> = GF(5^2); S
            Finite Field in b of size 5^2
            sage: S.prime_subfield()
            Finite Field of size 5
            sage: type(S.prime_subfield())
            <class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>
        """
        try:
            return self._prime_subfield
        except AttributeError:
            from .finite_field_constructor import GF
            self._prime_subfield = GF(self.characteristic())
            return self._prime_subfield

    def log_to_int(self, n):
        r"""
        Given an integer `n` this method returns ``i`` where ``i``
        satisfies `g^n = i` where `g` is the generator of ``self``; the
        result is interpreted as an integer.

        INPUT:

        - ``n`` -- log representation of a finite field element

        OUTPUT:

        integer representation of a finite field element.

        EXAMPLES::

            sage: k = GF(2**8, 'a')
            sage: k.log_to_int(4)
            16
            sage: k.log_to_int(20)
            180
        """
        return self._cache.log_to_int(n)

    def int_to_log(self, n):
        r"""
        Given an integer `n` this method returns `i` where `i` satisfies
        `g^i = n \mod p` where `g` is the generator and `p` is the
        characteristic of ``self``.

        INPUT:

        - ``n`` -- integer representation of an finite field element

        OUTPUT:

        log representation of ``n``

        EXAMPLES::

            sage: k = GF(7**3, 'a')
            sage: k.int_to_log(4)
            228
            sage: k.int_to_log(3)
            57
            sage: k.gen()^57
            3
        """
        return self._cache.int_to_log(n)

    def fetch_int(self, n):
        r"""
        Given an integer `n` return a finite field element in ``self``
        which equals `n` under the condition that :meth:`gen()` is set to
        :meth:`characteristic()`.

        EXAMPLES::

            sage: k.<a> = GF(2^8)
            sage: k.fetch_int(8)
            a^3
            sage: e = k.fetch_int(151); e
            a^7 + a^4 + a^2 + a + 1
            sage: 2^7 + 2^4 + 2^2 + 2 + 1
            151
        """
        return self._cache.fetch_int(n)

    def _pari_modulus(self):
        """
        Return the modulus of ``self`` in a format for PARI.

        EXAMPLES::

            sage: GF(3^4,'a')._pari_modulus()
            Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(2, 3)
        """
        f = pari(str(self.modulus()))
        return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())

    def __iter__(self):
        """
        Finite fields may be iterated over.

        EXAMPLES::

            sage: list(GF(2**2, 'a'))
            [0, a, a + 1, 1]
        """
        from .element_givaro import FiniteField_givaro_iterator
        return FiniteField_givaro_iterator(self._cache)

    def a_times_b_plus_c(self, a, b, c):
        """
        Return ``a*b + c``. This is faster than multiplying ``a`` and ``b``
        first and adding ``c`` to the result.

        INPUT:

        - ``a,b,c`` -- :class:`~~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`

        EXAMPLES::

            sage: k.<a> = GF(2**8)
            sage: k.a_times_b_plus_c(a,a,k(1))
            a^2 + 1
        """
        return self._cache.a_times_b_plus_c(a, b, c)

    def a_times_b_minus_c(self, a, b, c):
        """
        Return ``a*b - c``.

        INPUT:

        - ``a,b,c`` -- :class:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`

        EXAMPLES::

            sage: k.<a> = GF(3**3)
            sage: k.a_times_b_minus_c(a,a,k(1))
            a^2 + 2
        """
        return self._cache.a_times_b_minus_c(a, b, c)

    def c_minus_a_times_b(self, a, b, c):
        """
        Return ``c - a*b``.

        INPUT:

        - ``a,b,c`` -- :class:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`

        EXAMPLES::

            sage: k.<a> = GF(3**3)
            sage: k.c_minus_a_times_b(a,a,k(1))
            2*a^2 + 1
        """
        return self._cache.c_minus_a_times_b(a, b, c)

    def frobenius_endomorphism(self, n=1):
        """
        INPUT:

        -  ``n`` -- an integer (default: 1)

        OUTPUT:

        The `n`-th power of the absolute arithmetic Frobenius
        endomorphism on this finite field.

        EXAMPLES::

            sage: k.<t> = GF(3^5)
            sage: Frob = k.frobenius_endomorphism(); Frob
            Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5

            sage: a = k.random_element()
            sage: Frob(a) == a^3
            True

        We can specify a power::

            sage: k.frobenius_endomorphism(2)
            Frobenius endomorphism t |--> t^(3^2) on Finite Field in t of size 3^5

        The result is simplified if possible::

            sage: k.frobenius_endomorphism(6)
            Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5
            sage: k.frobenius_endomorphism(5)
            Identity endomorphism of Finite Field in t of size 3^5

        Comparisons work::

            sage: k.frobenius_endomorphism(6) == Frob
            True
            sage: from sage.categories.morphism import IdentityMorphism
            sage: k.frobenius_endomorphism(5) == IdentityMorphism(k)
            True

        AUTHOR:

        - Xavier Caruso (2012-06-29)
        """
        from sage.rings.finite_rings.hom_finite_field_givaro import FrobeniusEndomorphism_givaro
        return FrobeniusEndomorphism_givaro(self, n)
コード例 #10
0
class FiniteField_givaro(FiniteField):
    """
    Finite field implemented using Zech logs and the cardinality must be
    less than `2^{16}`. By default, conway polynomials are used as minimal
    polynomials.

    INPUT:

    - ``q`` -- `p^n` (must be prime power)

    - ``name`` -- (default: ``'a'``) variable used for
      :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.poly_repr()`

    - ``modulus`` -- (default: ``None``, a conway polynomial is used if found.
      Otherwise a random polynomial is used) A minimal polynomial to use for
      reduction or ``'random'`` to force a random irreducible polynomial.

    - ``repr`` -- (default: ``'poly'``) controls the way elements are printed
      to the user:

      - 'log': repr is
        :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.log_repr()`
      - 'int': repr is
        :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.int_repr()`
      - 'poly': repr is
        :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.poly_repr()`

    - cache -- (default: ``False``) if ``True`` a cache of all elements of
      this field is created. Thus, arithmetic does not create new elements
      which speeds calculations up. Also, if many elements are needed during a
      calculation this cache reduces the memory requirement as at most
      :meth:`order` elements are created.

    OUTPUT:

    Givaro finite field with characteristic `p` and cardinality `p^n`.

    EXAMPLES:

    By default conway polynomials are used::

        sage: k.<a> = GF(2**8)
        sage: -a ^ k.degree()
        a^4 + a^3 + a^2 + 1
        sage: f = k.modulus(); f
        x^8 + x^4 + x^3 + x^2 + 1

    You may enforce a modulus::

        sage: P.<x> = PolynomialRing(GF(2))
        sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael Polynomial
        sage: k.<a> = GF(2^8, modulus=f)
        sage: k.modulus()
        x^8 + x^4 + x^3 + x + 1
        sage: a^(2^8)
        a

    You may enforce a random modulus::

        sage: k = GF(3**5, 'a', modulus='random')
        sage: k.modulus() # random polynomial
        x^5 + 2*x^4 + 2*x^3 + x^2 + 2

    Three different representations are possible::

        sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='poly').gen()
        a
        sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='int').gen()
        3
        sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='log').gen()
        1
    """
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError, "Unknown representation %s" % repr

        q = Integer(q)
        if q < 2:
            raise ValueError, "q  must be a prime power"
        F = q.factor()
        if len(F) > 1:
            raise ValueError, "q must be a prime power"
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError, "q must be < 2^16"

        import constructor
        FiniteField.__init__(self,
                             constructor.FiniteField(p),
                             name,
                             normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        if modulus is None or modulus == 'conway':
            if k == 1:
                modulus = 'random'  # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.conway_polynomials import conway_polynomial
                modulus = conway_polynomial(p, k)
            elif modulus is None:
                modulus = 'random'
            else:
                raise ValueError, "Conway polynomial not found"

        from sage.rings.polynomial.all import is_Polynomial
        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)

    def characteristic(self):
        """
        Return the characteristic of this field.

        EXAMPLES::

            sage: p = GF(19^5,'a').characteristic(); p
            19
            sage: type(p)
            <type 'sage.rings.integer.Integer'>
        """
        return Integer(self._cache.characteristic())

    def order(self):
        """
        Return the cardinality of this field.

        OUTPUT:

        Integer -- the number of elements in ``self``.

        EXAMPLES::

            sage: n = GF(19^5,'a').order(); n
            2476099
            sage: type(n)
            <type 'sage.rings.integer.Integer'>
        """
        return self._cache.order()

    def degree(self):
        r"""
        If the cardinality of ``self`` is `p^n`, then this returns `n`.

        OUTPUT:

        Integer -- the degree

        EXAMPLES::

            sage: GF(3^4,'a').degree()
            4
        """
        return Integer(self._cache.exponent())

    def _repr_option(self, key):
        """
        Metadata about the :meth:`_repr_` output.

        See :meth:`sage.structure.parent._repr_option` for details.

        EXAMPLES::

            sage: GF(23**3, 'a', repr='log')._repr_option('element_is_atomic')
            True
            sage: GF(23**3, 'a', repr='int')._repr_option('element_is_atomic')
            True
            sage: GF(23**3, 'a', repr='poly')._repr_option('element_is_atomic')
            False
        """
        if key == 'element_is_atomic':
            return self._cache.repr != 0  # 0 means repr='poly'
        return super(FiniteField_givaro, self)._repr_option(key)

    def random_element(self, *args, **kwds):
        """
        Return a random element of ``self``.

        EXAMPLES::

            sage: k = GF(23**3, 'a')
            sage: e = k.random_element(); e
            2*a^2 + 14*a + 21
            sage: type(e)
            <type 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>

            sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))
            sage: P.random_element(5)
            2*a + 2 + (a^2 + a + 2)*x + (2*a + 1)*x^2 + (2*a^2 + a)*x^3 + 2*a^2*x^4 + O(x^5)
        """
        return self._cache.random_element()

    def _element_constructor_(self, e):
        """
        Coerces several data types to ``self``.

        INPUT:

        - ``e`` -- data to coerce

        EXAMPLES:

        :class:`FiniteField_givaroElement` are accepted where the parent
        is either ``self``, equals ``self`` or is the prime subfield::

            sage: k = GF(2**8, 'a')
            sage: k.gen() == k(k.gen())
            True

        Floats, ints, longs, Integer are interpreted modulo characteristic::

            sage: k(2) # indirect doctest
            0

            Floats coerce in:
            sage: k(float(2.0))
            0

        Rational are interpreted as ``self(numerator)/self(denominator)``.
        Both may not be greater than :meth:characteristic()`.
        ::

            sage: k = GF(3**8, 'a')
            sage: k(1/2) == k(1)/k(2)
            True

        Free module elements over :meth:`prime_subfield()` are interpreted
        'little endian'::

            sage: k = GF(2**8, 'a')
            sage: e = k.vector_space().gen(1); e
            (0, 1, 0, 0, 0, 0, 0, 0)
            sage: k(e)
            a

        ``None`` yields zero::

            sage: k(None)
            0

        Strings are evaluated as polynomial representation of elements in
        ``self``::

            sage: k('a^2+1')
            a^2 + 1

        Univariate polynomials coerce into finite fields by evaluating
        the polynomial at the field's generator::

            sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
            sage: R.<x> = QQ[]
            sage: k, a = FiniteField_givaro(5^2, 'a').objgen()
            sage: k(R(2/3))
            4
            sage: k(x^2)
            a + 3
            sage: R.<x> = GF(5)[]
            sage: k(x^3-2*x+1)
            2*a + 4

            sage: x = polygen(QQ)
            sage: k(x^25)
            a

            sage: Q, q = FiniteField_givaro(5^3,'q').objgen()
            sage: L = GF(5)
            sage: LL.<xx> = L[]
            sage: Q(xx^2 + 2*xx + 4)
            q^2 + 2*q + 4


        Multivariate polynomials only coerce if constant::

            sage: R = k['x,y,z']; R
            Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2
            sage: k(R(2))
            2
            sage: R = QQ['x,y,z']
            sage: k(R(1/5))
            Traceback (most recent call last):
            ...
            ZeroDivisionError: division by zero in finite field.


        PARI elements are interpreted as finite field elements; this PARI
        flexibility is (absurdly!) liberal::

            sage: k = GF(2**8, 'a')
            sage: k(pari('Mod(1,2)'))
            1
            sage: k(pari('Mod(2,3)'))
            0
            sage: k(pari('Mod(1,3)*a^20'))
            a^7 + a^5 + a^4 + a^2

        GAP elements need to be finite field elements::

            sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
            sage: x = gap('Z(13)')
            sage: F = FiniteField_givaro(13)
            sage: F(x)
            2
            sage: F(gap('0*Z(13)'))
            0
            sage: F = FiniteField_givaro(13^2)
            sage: x = gap('Z(13)')
            sage: F(x)
            2
            sage: x = gap('Z(13^2)^3')
            sage: F(x)
            12*a + 11
            sage: F.multiplicative_generator()^3
            12*a + 11

            sage: k.<a> = GF(29^3)
            sage: k(48771/1225)
            28

            sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
            sage: F9 = FiniteField_givaro(9)
            sage: F81 = FiniteField_givaro(81)
            sage: F81(F9.gen())
            Traceback (most recent call last):
            ...
            TypeError: unable to coerce from a finite field other than the prime subfield
        """
        return self._cache.element_from_data(e)

    def _coerce_map_from_(self, R):
        """
        Returns ``True`` if this finite field has a coercion map from ``R``.

        EXAMPLES::

            sage: k.<a> = GF(3^8)
            sage: a + 1 # indirect doctest
            a + 1
            sage: a + int(1)
            a + 1
            sage: a + GF(3)(1)
            a + 1
        """
        from sage.rings.integer_ring import ZZ
        from sage.rings.finite_rings.finite_field_base import is_FiniteField
        from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic
        if R is int or R is long or R is ZZ:
            return True
        if is_FiniteField(R):
            if R is self:
                return True
            from sage.rings.residue_field import ResidueField_generic
            if isinstance(R, ResidueField_generic):
                return False
            if R.characteristic() == self.characteristic():
                if isinstance(R, IntegerModRing_generic):
                    return True
                if R.degree() == 1:
                    return True
                elif self.degree() % R.degree() == 0:
                    # This is where we *would* do coercion from one nontrivial finite field to another...
                    # We use this error message for backward compatibility until #8335 is finished
                    raise TypeError, "unable to coerce from a finite field other than the prime subfield"

    def gen(self, n=0):
        r"""
        Return a generator of ``self``.

        All elements ``x`` of ``self`` are expressed as `\log_{g}(p)`
        internally where `g` is the generator of ``self``.

        This generator might differ between different runs or
        different architectures.

        .. WARNING::

            The generator is not guaranteed to be a generator for
            the multiplicative group.  To obtain the latter, use
            :meth:`~sage.rings.finite_rings.finite_field_base.FiniteFields.multiplicative_generator`.

        EXAMPLES::

            sage: k = GF(3^4, 'b'); k.gen()
            b
            sage: k.gen(1)
            Traceback (most recent call last):
            ...
            IndexError: only one generator
            sage: F = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(31)
            sage: F.gen()
            1
        """
        if n > 0:
            raise IndexError, "only one generator"
        return self._cache.gen()

    def prime_subfield(self):
        r"""
        Return the prime subfield `\GF{p}` of self if ``self`` is `\GF{p^n}`.

        EXAMPLES::

            sage: GF(3^4, 'b').prime_subfield()
            Finite Field of size 3

            sage: S.<b> = GF(5^2); S
            Finite Field in b of size 5^2
            sage: S.prime_subfield()
            Finite Field of size 5
            sage: type(S.prime_subfield())
            <class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>
        """
        try:
            return self._prime_subfield
        except AttributeError:
            import constructor
            self._prime_subfield = constructor.FiniteField(
                self.characteristic())
            return self._prime_subfield

    def log_to_int(self, n):
        r"""
        Given an integer `n` this method returns ``i`` where ``i``
        satisfies `g^n = i` where `g` is the generator of ``self``; the
        result is interpreted as an integer.

        INPUT:

        - ``n`` -- log representation of a finite field element

        OUTPUT:

        integer representation of a finite field element.

        EXAMPLES::

            sage: k = GF(2**8, 'a')
            sage: k.log_to_int(4)
            16
            sage: k.log_to_int(20)
            180
        """
        return self._cache.log_to_int(n)

    def int_to_log(self, n):
        r"""
        Given an integer `n` this method returns `i` where `i` satisfies
        `g^i = n \mod p` where `g` is the generator and `p` is the
        characteristic of ``self``.

        INPUT:

        - ``n`` -- integer representation of an finite field element

        OUTPUT:

        log representation of ``n``

        EXAMPLES::

            sage: k = GF(7**3, 'a')
            sage: k.int_to_log(4)
            228
            sage: k.int_to_log(3)
            57
            sage: k.gen()^57
            3
        """
        return self._cache.int_to_log(n)

    def fetch_int(self, n):
        r"""
        Given an integer `n` return a finite field element in ``self``
        which equals `n` under the condition that :meth:`gen()` is set to
        :meth:`characteristic()`.

        EXAMPLES::

            sage: k.<a> = GF(2^8)
            sage: k.fetch_int(8)
            a^3
            sage: e = k.fetch_int(151); e
            a^7 + a^4 + a^2 + a + 1
            sage: 2^7 + 2^4 + 2^2 + 2 + 1
            151
        """
        return self._cache.fetch_int(n)

    def polynomial(self, name=None):
        """
        Return the defining polynomial of this field as an element of
        :class:`PolynomialRing`.

        This is the same as the characteristic polynomial of the
        generator of ``self``.

        INPUT:

        - ``name`` -- optional name of the generator

        EXAMPLES::

            sage: k = GF(3^4, 'a')
            sage: k.polynomial()
            a^4 + 2*a^3 + 2
        """
        if name is not None:
            try:
                return self._polynomial
            except AttributeError:
                pass
        quo = (-(self.gen()**(self.degree()))).integer_representation()
        b = int(self.characteristic())

        ret = []
        for i in range(self.degree()):
            ret.append(quo % b)
            quo = quo / b
        ret = ret + [1]
        R = self.polynomial_ring(name)
        if name is None:
            self._polynomial = R(ret)
            return self._polynomial
        else:
            return R(ret)

    def __hash__(self):
        """
        The hash of a Givaro finite field is a hash over it's
        characteristic polynomial and the string 'givaro'.

        EXAMPLES::

            sage: {GF(3^4, 'a'):1} # indirect doctest
            {Finite Field in a of size 3^4: 1}
        """
        try:
            return self._hash
        except AttributeError:
            if self.degree() > 1:
                self._hash = hash((self.characteristic(), self.polynomial(),
                                   self.variable_name(), "givaro"))
            else:
                self._hash = hash(
                    (self.characteristic(), self.variable_name(), "givaro"))
            return self._hash

    def _pari_modulus(self):
        """
        Return the modulus of ``self`` in a format for PARI.

        EXAMPLES::

            sage: GF(3^4,'a')._pari_modulus()
            Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(2, 3)
        """
        f = pari(str(self.modulus()))
        return f.subst('x', 'a') * pari("Mod(1,%s)" % self.characteristic())

    def _finite_field_ext_pari_(self):  # todo -- cache
        """
        Return a :class:`FiniteField_ext_pari` isomorphic to ``self`` with
        the same defining polynomial.

        EXAMPLES::

            sage: GF(3^4,'z')._finite_field_ext_pari_()
            Finite Field in z of size 3^4
        """
        f = self.polynomial()
        import finite_field_ext_pari
        return finite_field_ext_pari.FiniteField_ext_pari(
            self.order(), self.variable_name(), f)

    def __iter__(self):
        """
        Finite fields may be iterated over.

        EXAMPLES::

            sage: list(GF(2**2, 'a'))
            [0, a, a + 1, 1]
        """
        from element_givaro import FiniteField_givaro_iterator
        return FiniteField_givaro_iterator(self._cache)

    def a_times_b_plus_c(self, a, b, c):
        """
        Return ``a*b + c``. This is faster than multiplying ``a`` and ``b``
        first and adding ``c`` to the result.

        INPUT:

        - ``a,b,c`` -- :class:`~~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`

        EXAMPLES::

            sage: k.<a> = GF(2**8)
            sage: k.a_times_b_plus_c(a,a,k(1))
            a^2 + 1
        """
        return self._cache.a_times_b_plus_c(a, b, c)

    def a_times_b_minus_c(self, a, b, c):
        """
        Return ``a*b - c``.

        INPUT:

        - ``a,b,c`` -- :class:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`

        EXAMPLES::

            sage: k.<a> = GF(3**3)
            sage: k.a_times_b_minus_c(a,a,k(1))
            a^2 + 2
        """
        return self._cache.a_times_b_minus_c(a, b, c)

    def c_minus_a_times_b(self, a, b, c):
        """
        Return ``c - a*b``.

        INPUT:

        - ``a,b,c`` -- :class:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`

        EXAMPLES::

            sage: k.<a> = GF(3**3)
            sage: k.c_minus_a_times_b(a,a,k(1))
            2*a^2 + 1
        """
        return self._cache.c_minus_a_times_b(a, b, c)
コード例 #11
0
class FiniteField_givaro(FiniteField):
    """
    Finite field implemented using Zech logs and the cardinality must be
    less than `2^{16}`. By default, conway polynomials are used as minimal
    polynomials.

    INPUT:

    - ``q`` -- `p^n` (must be prime power)

    - ``name`` -- (default: ``'a'``) variable used for
      :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.poly_repr()`

    - ``modulus`` -- (default: ``None``, a conway polynomial is used if found.
      Otherwise a random polynomial is used) A minimal polynomial to use for
      reduction or ``'random'`` to force a random irreducible polynomial.

    - ``repr`` -- (default: ``'poly'``) controls the way elements are printed
      to the user:

      - 'log': repr is
        :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.log_repr()`
      - 'int': repr is
        :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.int_repr()`
      - 'poly': repr is
        :meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.poly_repr()`

    - cache -- (default: ``False``) if ``True`` a cache of all elements of
      this field is created. Thus, arithmetic does not create new elements
      which speeds calculations up. Also, if many elements are needed during a
      calculation this cache reduces the memory requirement as at most
      :meth:`order` elements are created.

    OUTPUT:

    Givaro finite field with characteristic `p` and cardinality `p^n`.

    EXAMPLES:

    By default conway polynomials are used::

        sage: k.<a> = GF(2**8)
        sage: -a ^ k.degree()
        a^4 + a^3 + a^2 + 1
        sage: f = k.modulus(); f
        x^8 + x^4 + x^3 + x^2 + 1

    You may enforce a modulus::
        
        sage: P.<x> = PolynomialRing(GF(2))
        sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael Polynomial
        sage: k.<a> = GF(2^8, modulus=f)
        sage: k.modulus()
        x^8 + x^4 + x^3 + x + 1
        sage: a^(2^8)
        a

    You may enforce a random modulus::

        sage: k = GF(3**5, 'a', modulus='random')
        sage: k.modulus() # random polynomial
        x^5 + 2*x^4 + 2*x^3 + x^2 + 2

    Three different representations are possible::

        sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='poly').gen()
        a
        sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='int').gen()
        3
        sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='log').gen()
        1
    """

    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ["int", "log", "poly"]:
            raise ValueError, "Unknown representation %s" % repr

        q = Integer(q)
        if q < 2:
            raise ValueError, "q  must be a prime power"
        F = q.factor()
        if len(F) > 1:
            raise ValueError, "q must be a prime power"
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError, "q must be < 2^16"

        import constructor

        FiniteField.__init__(self, constructor.FiniteField(p), name, normalize=False)

        self._kwargs["repr"] = repr
        self._kwargs["cache"] = cache

        self._is_conway = False
        if modulus is None or modulus == "conway":
            if k == 1:
                modulus = "random"  # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.constructor import conway_polynomial

                modulus = conway_polynomial(p, k)
                self._is_conway = True
            elif modulus is None:
                modulus = "random"
            else:
                raise ValueError, "Conway polynomial not found"

        from sage.rings.polynomial.all import is_Polynomial

        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)

    def characteristic(self):
        """
        Return the characteristic of this field.

        EXAMPLES::

            sage: p = GF(19^5,'a').characteristic(); p
            19
            sage: type(p)
            <type 'sage.rings.integer.Integer'>
        """
        return Integer(self._cache.characteristic())

    def order(self):
        """
        Return the cardinality of this field.

        OUTPUT:

        Integer -- the number of elements in ``self``.

        EXAMPLES::

            sage: n = GF(19^5,'a').order(); n
            2476099
            sage: type(n)
            <type 'sage.rings.integer.Integer'>        
        """
        return self._cache.order()

    def degree(self):
        r"""
        If the cardinality of ``self`` is `p^n`, then this returns `n`.

        OUTPUT:

        Integer -- the degree

        EXAMPLES::

            sage: GF(3^4,'a').degree()
            4
        """
        return Integer(self._cache.exponent())

    def _repr_option(self, key):
        """
        Metadata about the :meth:`_repr_` output.

        See :meth:`sage.structure.parent._repr_option` for details.

        EXAMPLES::

            sage: GF(23**3, 'a', repr='log')._repr_option('element_is_atomic')
            True
            sage: GF(23**3, 'a', repr='int')._repr_option('element_is_atomic')
            True
            sage: GF(23**3, 'a', repr='poly')._repr_option('element_is_atomic')
            False
        """
        if key == "element_is_atomic":
            return self._cache.repr != 0  # 0 means repr='poly'
        return super(FiniteField_givaro, self)._repr_option(key)

    def random_element(self, *args, **kwds):
        """
        Return a random element of ``self``.

        EXAMPLES::

            sage: k = GF(23**3, 'a')
            sage: e = k.random_element(); e
            2*a^2 + 14*a + 21
            sage: type(e)
            <type 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>

            sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))
            sage: P.random_element(5)
            2*a + 2 + (a^2 + a + 2)*x + (2*a + 1)*x^2 + (2*a^2 + a)*x^3 + 2*a^2*x^4 + O(x^5)
        """
        return self._cache.random_element()

    def _element_constructor_(self, e):
        """
        Coerces several data types to ``self``.

        INPUT:
        
        - ``e`` -- data to coerce

        EXAMPLES:

        :class:`FiniteField_givaroElement` are accepted where the parent
        is either ``self``, equals ``self`` or is the prime subfield::
        
            sage: k = GF(2**8, 'a')
            sage: k.gen() == k(k.gen())
            True

        Floats, ints, longs, Integer are interpreted modulo characteristic::
            
            sage: k(2) # indirect doctest
            0

            Floats coerce in:
            sage: k(float(2.0))
            0
            
        Rational are interpreted as ``self(numerator)/self(denominator)``.
        Both may not be greater than :meth:characteristic()`.
        ::

            sage: k = GF(3**8, 'a')
            sage: k(1/2) == k(1)/k(2)
            True

        Free module elements over :meth:`prime_subfield()` are interpreted
        'little endian'::
            
            sage: k = GF(2**8, 'a')
            sage: e = k.vector_space().gen(1); e
            (0, 1, 0, 0, 0, 0, 0, 0)
            sage: k(e)
            a

        ``None`` yields zero::

            sage: k(None)
            0

        Strings are evaluated as polynomial representation of elements in
        ``self``::

            sage: k('a^2+1')
            a^2 + 1

        Univariate polynomials coerce into finite fields by evaluating
        the polynomial at the field's generator::

            sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
            sage: R.<x> = QQ[]
            sage: k, a = FiniteField_givaro(5^2, 'a').objgen()
            sage: k(R(2/3))
            4
            sage: k(x^2)
            a + 3
            sage: R.<x> = GF(5)[]
            sage: k(x^3-2*x+1)
            2*a + 4

            sage: x = polygen(QQ)
            sage: k(x^25)
            a

            sage: Q, q = FiniteField_givaro(5^3,'q').objgen()
            sage: L = GF(5)
            sage: LL.<xx> = L[]
            sage: Q(xx^2 + 2*xx + 4)
            q^2 + 2*q + 4


        Multivariate polynomials only coerce if constant::

            sage: R = k['x,y,z']; R
            Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2
            sage: k(R(2))
            2
            sage: R = QQ['x,y,z']
            sage: k(R(1/5))
            Traceback (most recent call last):
            ...
            ZeroDivisionError: division by zero in finite field.

        
        PARI elements are interpreted as finite field elements; this PARI
        flexibility is (absurdly!) liberal::

            sage: k = GF(2**8, 'a')
            sage: k(pari('Mod(1,2)'))
            1
            sage: k(pari('Mod(2,3)'))
            0
            sage: k(pari('Mod(1,3)*a^20'))
            a^7 + a^5 + a^4 + a^2

        GAP elements need to be finite field elements::

            sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
            sage: x = gap('Z(13)')
            sage: F = FiniteField_givaro(13)
            sage: F(x)
            2
            sage: F(gap('0*Z(13)'))
            0
            sage: F = FiniteField_givaro(13^2)
            sage: x = gap('Z(13)')
            sage: F(x)
            2
            sage: x = gap('Z(13^2)^3')
            sage: F(x)
            12*a + 11
            sage: F.multiplicative_generator()^3
            12*a + 11

            sage: k.<a> = GF(29^3)
            sage: k(48771/1225)
            28

            sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
            sage: F9 = FiniteField_givaro(9)
            sage: F81 = FiniteField_givaro(81)
            sage: F81(F9.gen())
            Traceback (most recent call last):
            ...
            TypeError: unable to coerce from a finite field other than the prime subfield
        """
        return self._cache.element_from_data(e)

    def _coerce_map_from_(self, R):
        """
        Returns ``True`` if this finite field has a coercion map from ``R``.

        EXAMPLES::

            sage: k.<a> = GF(3^8)
            sage: a + 1 # indirect doctest
            a + 1
            sage: a + int(1)
            a + 1
            sage: a + GF(3)(1)
            a + 1
        """
        from sage.rings.integer_ring import ZZ
        from sage.rings.finite_rings.finite_field_base import is_FiniteField
        from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic

        if R is int or R is long or R is ZZ:
            return True
        if is_FiniteField(R):
            if R is self:
                return True
            from sage.rings.residue_field import ResidueField_generic

            if isinstance(R, ResidueField_generic):
                return False
            if R.characteristic() == self.characteristic():
                if isinstance(R, IntegerModRing_generic):
                    return True
                if R.degree() == 1:
                    return True
                elif self.degree() % R.degree() == 0:
                    # This is where we *would* do coercion from one nontrivial finite field to another...
                    # We use this error message for backward compatibility until #8335 is finished
                    raise TypeError, "unable to coerce from a finite field other than the prime subfield"

    def gen(self, n=0):
        r"""
        Return a generator of ``self``.

        All elements ``x`` of ``self`` are expressed as `\log_{g}(p)`
        internally where `g` is the generator of ``self``.

        This generator might differ between different runs or
        different architectures.

        .. WARNING::

            The generator is not guaranteed to be a generator for
            the multiplicative group.  To obtain the latter, use
            :meth:`~sage.rings.finite_rings.finite_field_base.FiniteFields.multiplicative_generator`.

        EXAMPLES::

            sage: k = GF(3^4, 'b'); k.gen()
            b
            sage: k.gen(1)
            Traceback (most recent call last):
            ...
            IndexError: only one generator
            sage: F = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(31)
            sage: F.gen()
            1
        """
        if n > 0:
            raise IndexError, "only one generator"
        return self._cache.gen()

    def prime_subfield(self):
        r"""
        Return the prime subfield `\GF{p}` of self if ``self`` is `\GF{p^n}`.

        EXAMPLES::

            sage: GF(3^4, 'b').prime_subfield()
            Finite Field of size 3

            sage: S.<b> = GF(5^2); S
            Finite Field in b of size 5^2
            sage: S.prime_subfield()
            Finite Field of size 5
            sage: type(S.prime_subfield())
            <class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>
        """
        try:
            return self._prime_subfield
        except AttributeError:
            import constructor

            self._prime_subfield = constructor.FiniteField(self.characteristic())
            return self._prime_subfield

    def log_to_int(self, n):
        r"""
        Given an integer `n` this method returns ``i`` where ``i``
        satisfies `g^n = i` where `g` is the generator of ``self``; the
        result is interpreted as an integer.

        INPUT:

        - ``n`` -- log representation of a finite field element

        OUTPUT:

        integer representation of a finite field element.

        EXAMPLES::

            sage: k = GF(2**8, 'a')
            sage: k.log_to_int(4)
            16
            sage: k.log_to_int(20)
            180
        """
        return self._cache.log_to_int(n)

    def int_to_log(self, n):
        r"""
        Given an integer `n` this method returns `i` where `i` satisfies
        `g^i = n \mod p` where `g` is the generator and `p` is the
        characteristic of ``self``.

        INPUT:

        - ``n`` -- integer representation of an finite field element

        OUTPUT:

        log representation of ``n``

        EXAMPLES::

            sage: k = GF(7**3, 'a')
            sage: k.int_to_log(4)
            228
            sage: k.int_to_log(3)
            57
            sage: k.gen()^57
            3
        """
        return self._cache.int_to_log(n)

    def fetch_int(self, n):
        r"""
        Given an integer `n` return a finite field element in ``self``
        which equals `n` under the condition that :meth:`gen()` is set to
        :meth:`characteristic()`.

        EXAMPLES::

            sage: k.<a> = GF(2^8)
            sage: k.fetch_int(8)
            a^3
            sage: e = k.fetch_int(151); e
            a^7 + a^4 + a^2 + a + 1
            sage: 2^7 + 2^4 + 2^2 + 2 + 1
            151
        """
        return self._cache.fetch_int(n)

    def polynomial(self, name=None):
        """
        Return the defining polynomial of this field as an element of
        :class:`PolynomialRing`.
        
        This is the same as the characteristic polynomial of the
        generator of ``self``.

        INPUT:

        - ``name`` -- optional name of the generator

        EXAMPLES::

            sage: k = GF(3^4, 'a')
            sage: k.polynomial()
            a^4 + 2*a^3 + 2        
        """
        if name is not None:
            try:
                return self._polynomial
            except AttributeError:
                pass
        quo = (-(self.gen() ** (self.degree()))).integer_representation()
        b = int(self.characteristic())

        ret = []
        for i in range(self.degree()):
            ret.append(quo % b)
            quo = quo / b
        ret = ret + [1]
        R = self.polynomial_ring(name)
        if name is None:
            self._polynomial = R(ret)
            return self._polynomial
        else:
            return R(ret)

    def __hash__(self):
        """
        The hash of a Givaro finite field is a hash over it's
        characteristic polynomial and the string 'givaro'.

        EXAMPLES::

            sage: {GF(3^4, 'a'):1} # indirect doctest
            {Finite Field in a of size 3^4: 1}
        """
        try:
            return self._hash
        except AttributeError:
            if self.degree() > 1:
                self._hash = hash((self.characteristic(), self.polynomial(), self.variable_name(), "givaro"))
            else:
                self._hash = hash((self.characteristic(), self.variable_name(), "givaro"))
            return self._hash

    def _pari_modulus(self):
        """
        Return the modulus of ``self`` in a format for PARI.

        EXAMPLES::

            sage: GF(3^4,'a')._pari_modulus()
            Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(2, 3)        
        """
        f = pari(str(self.modulus()))
        return f.subst("x", "a") * pari("Mod(1,%s)" % self.characteristic())

    def _finite_field_ext_pari_(self):  # todo -- cache
        """
        Return a :class:`FiniteField_ext_pari` isomorphic to ``self`` with
        the same defining polynomial.

        EXAMPLES::

            sage: GF(3^4,'z')._finite_field_ext_pari_()
            Finite Field in z of size 3^4
        """
        f = self.polynomial()
        import finite_field_ext_pari

        return finite_field_ext_pari.FiniteField_ext_pari(self.order(), self.variable_name(), f)

    def __iter__(self):
        """
        Finite fields may be iterated over.

        EXAMPLES::

            sage: list(GF(2**2, 'a'))
            [0, a, a + 1, 1]
        """
        from element_givaro import FiniteField_givaro_iterator

        return FiniteField_givaro_iterator(self._cache)

    def a_times_b_plus_c(self, a, b, c):
        """
        Return ``a*b + c``. This is faster than multiplying ``a`` and ``b``
        first and adding ``c`` to the result.

        INPUT:

        - ``a,b,c`` -- :class:`~~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`

        EXAMPLES::

            sage: k.<a> = GF(2**8)
            sage: k.a_times_b_plus_c(a,a,k(1))
            a^2 + 1
        """
        return self._cache.a_times_b_plus_c(a, b, c)

    def a_times_b_minus_c(self, a, b, c):
        """
        Return ``a*b - c``.

        INPUT:

        - ``a,b,c`` -- :class:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`

        EXAMPLES::

            sage: k.<a> = GF(3**3)
            sage: k.a_times_b_minus_c(a,a,k(1))
            a^2 + 2
        """
        return self._cache.a_times_b_minus_c(a, b, c)

    def c_minus_a_times_b(self, a, b, c):
        """
        Return ``c - a*b``.

        INPUT:

        - ``a,b,c`` -- :class:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`

        EXAMPLES::

            sage: k.<a> = GF(3**3)
            sage: k.c_minus_a_times_b(a,a,k(1))
            2*a^2 + 1
        """
        return self._cache.c_minus_a_times_b(a, b, c)
コード例 #12
0
ファイル: finite_field_givaro.py プロジェクト: dagss/sage
class FiniteField_givaro(FiniteField):
    def __init__(self, q, name="a",  modulus=None, repr="poly", cache=False):
        """
        Finite Field. These are implemented using Zech logs and the
        cardinality must be < 2^16. By default conway polynomials are
        used as minimal polynomial.

        INPUT:
            q     -- p^n (must be prime power)
            name  -- variable used for poly_repr (default: 'a')
            modulus -- you may provide a minimal polynomial to use for
                     reduction or 'random' to force a random
                     irreducible polynomial. (default: None, a conway
                     polynomial is used if found. Otherwise a random
                     polynomial is used)
            repr  -- controls the way elements are printed to the user:
                     (default: 'poly')
                     'log': repr is element.log_repr()
                     'int': repr is element.int_repr()
                     'poly': repr is element.poly_repr()
            cache -- if True a cache of all elements of this field is
                     created. Thus, arithmetic does not create new
                     elements which speeds calculations up. Also, if
                     many elements are needed during a calculation
                     this cache reduces the memory requirement as at
                     most self.order() elements are created. (default: False)

        OUTPUT:
            Givaro finite field with characteristic p and cardinality p^n.

        EXAMPLES:

            By default conway polynomials are used:
        
            sage: k.<a> = GF(2**8)
            sage: -a ^ k.degree()
            a^4 + a^3 + a^2 + 1
            sage: f = k.modulus(); f 
            x^8 + x^4 + x^3 + x^2 + 1

            You may enforce a modulus:
            
            sage: P.<x> = PolynomialRing(GF(2))
            sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael Polynomial
            sage: k.<a> = GF(2^8, modulus=f)
            sage: k.modulus()
            x^8 + x^4 + x^3 + x + 1
            sage: a^(2^8)
            a

            You may enforce a random modulus:

            sage: k = GF(3**5, 'a', modulus='random')
            sage: k.modulus() # random polynomial
            x^5 + 2*x^4 + 2*x^3 + x^2 + 2

            Three different representations are possible:
            
            sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='poly').gen()
            a
            sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='int').gen()
            3
            sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='log').gen()
            5

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False
            
            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(j).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError, "Unknown representation %s"%repr

        q = Integer(q)
        if q < 2:
            raise ValueError, "q  must be a prime power"
        F = q.factor()
        if len(F) > 1:
            raise ValueError, "q must be a prime power"
        p = F[0][0]
        k = F[0][1]

        if q >= 1<<16:
            raise ValueError, "q must be < 2^16"

        import constructor
        FiniteField.__init__(self, constructor.FiniteField(p), name, normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        self._is_conway = False
        if modulus is None or modulus == 'conway':
            if k == 1:
                modulus = 'random' # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.constructor import conway_polynomial
                modulus = conway_polynomial(p, k)
                self._is_conway = True
            elif modulus is None:
                modulus = 'random'
            else:
                raise ValueError, "Conway polynomial not found"
                
        from sage.rings.polynomial.all import is_Polynomial
        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)

    def characteristic(self):
        """
        Return the characteristic of this field.

        EXAMPLES:
            sage: p = GF(19^5,'a').characteristic(); p
            19
            sage: type(p)
            <type 'sage.rings.integer.Integer'>
        """
        return Integer(self._cache.characteristic())

    def order(self):
        """
        Return the cardinality of this field.

        OUTPUT:
            Integer -- the number of elements in self.

        EXAMPLES:
            sage: n = GF(19^5,'a').order(); n
            2476099
            sage: type(n)
            <type 'sage.rings.integer.Integer'>        
        """
        return self._cache.order()

    def degree(self):
        r"""
        If \code{self.cardinality() == p^n} this method returns $n$.

        OUTPUT:
            Integer -- the degree

        EXAMPLES:
            sage: GF(3^4,'a').degree()
            4
        """
        return Integer(self._cache.exponent())

    def is_atomic_repr(self):
        """
        Return whether elements of self are printed using an atomic
        representation.
        
        EXAMPLES:
            sage: GF(3^4,'a').is_atomic_repr()
            False        
        """
        if self._cache.repr==0: #modulus
            return False
        else:
            return True
 
    def random_element(self, *args, **kwds):
        """
        Return a random element of self.

        INPUT:
            *args -- ignored
            **kwds -- ignored

        EXAMPLES:
            sage: k = GF(23**3, 'a')
            sage: e = k.random_element(); e
            9*a^2 + 10*a + 3
            sage: type(e)
            <type 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>

            sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))
            sage: P.random_element(5)
            a^2 + 2*a + 1 + (a + 1)*x + (a^2 + a + 1)*x^2 + (a^2 + 1)*x^3 + (2*a^2 + a)*x^4 + O(x^5)
        """
        return self._cache.random_element()

    def _element_constructor_(self, e):
        """
        Coerces several data types to self.

        INPUT:
        
        e -- data to coerce

        EXAMPLES:

        FiniteField_givaroElement are accepted where the parent
        is either self, equals self or is the prime subfield::
        
            sage: k = GF(2**8, 'a')
            sage: k.gen() == k(k.gen())
            True

        Floats, ints, longs, Integer are interpreted modulo characteristic::
            
            sage: k(2) # indirect doctest
            0

            Floats coerce in:
            sage: k(float(2.0))
            0
            
        Rational are interpreted as self(numerator)/self(denominator).
        Both may not be >= self.characteristic().
        ::

            sage: k = GF(3**8, 'a')
            sage: k(1/2) == k(1)/k(2)
            True

        Free module elements over self.prime_subfield() are interpreted 'little endian'::
            
            sage: k = GF(2**8, 'a')
            sage: e = k.vector_space().gen(1); e
            (0, 1, 0, 0, 0, 0, 0, 0)
            sage: k(e)
            a

        'None' yields zero::

            sage: k(None)
            0

        Strings are evaluated as polynomial representation of elements in self::

            sage: k('a^2+1')
            a^2 + 1

        Univariate polynomials coerce into finite fields by evaluating
        the polynomial at the field's generator::

            sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
            sage: R.<x> = QQ[]
            sage: k, a = FiniteField_givaro(5^2, 'a').objgen()
            sage: k(R(2/3))
            4
            sage: k(x^2)
            a + 3
            sage: R.<x> = GF(5)[]
            sage: k(x^3-2*x+1)
            2*a + 4

            sage: x = polygen(QQ)
            sage: k(x^25)
            a

            sage: Q, q = FiniteField_givaro(5^3,'q').objgen()
            sage: L = GF(5)
            sage: LL.<xx> = L[]
            sage: Q(xx^2 + 2*xx + 4)
            q^2 + 2*q + 4


        Multivariate polynomials only coerce if constant::

            sage: R = k['x,y,z']; R
            Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2
            sage: k(R(2))
            2
            sage: R = QQ['x,y,z']
            sage: k(R(1/5))
            Traceback (most recent call last):
            ...
            ZeroDivisionError: division by zero in finite field.

        
        PARI elements are interpreted as finite field elements; this PARI flexibility
        is (absurdly!) liberal::

            sage: k = GF(2**8, 'a')
            sage: k(pari('Mod(1,2)'))
            1
            sage: k(pari('Mod(2,3)'))
            0
            sage: k(pari('Mod(1,3)*a^20'))
            a^7 + a^5 + a^4 + a^2

        GAP elements need to be finite field elements::

            sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
            sage: x = gap('Z(13)')
            sage: F = FiniteField_givaro(13)
            sage: F(x)
            2
            sage: F(gap('0*Z(13)'))
            0
            sage: F = FiniteField_givaro(13^2)
            sage: x = gap('Z(13)')
            sage: F(x)
            2
            sage: x = gap('Z(13^2)^3')
            sage: F(x)
            12*a + 11
            sage: F.multiplicative_generator()^3
            12*a + 11

            sage: k.<a> = GF(29^3)
            sage: k(48771/1225)
            28

            sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
            sage: F9 = FiniteField_givaro(9)
            sage: F81 = FiniteField_givaro(81)
            sage: F81(F9.gen())
            Traceback (most recent call last):
            ...
            TypeError: unable to coerce from a finite field other than the prime subfield
        """
        return self._cache.element_from_data(e)

    def _coerce_map_from_(self, R):
        """
        Returns True if this finite field has a coercion map from R.

        EXAMPLES::

            sage: k.<a> = GF(3^8)
            sage: a + 1 # indirect doctest
            a + 1
            sage: a + int(1)
            a + 1
            sage: a + GF(3)(1)
            a + 1
        """
        from sage.rings.integer_ring import ZZ
        from sage.rings.finite_rings.finite_field_base import is_FiniteField
        from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic
        if R is int or R is long or R is ZZ:
            return True
        if is_FiniteField(R):
            if R is self:
                return True
            from sage.rings.residue_field import ResidueField_generic
            if isinstance(R, ResidueField_generic):
                return False
            if R.characteristic() == self.characteristic():
                if isinstance(R, IntegerModRing_generic): 
                    return True
                if R.degree() == 1:
                    return True
                elif self.degree() % R.degree() == 0:
                    # This is where we *would* do coercion from one nontrivial finite field to another...
                    # We use this error message for backward compatibility until #8335 is finished
                    raise TypeError, "unable to coerce from a finite field other than the prime subfield"

    def gen(self, n=0):
        r"""
        Return a generator of self. All elements x of self are
        expressed as $\log_{self.gen()}(p)$ internally.

        This generator might differ between different runs or
        different architectures.

        WARNING: The generator is not guaranteed to be a generator for
            the multiplicative group.  To obtain the latter, use
            multiplicative_generator().

        EXAMPLES:
            sage: k = GF(3^4, 'b'); k.gen()
            b
            sage: k.gen(1)
            Traceback (most recent call last):
            ...
            IndexError: only one generator
            sage: F = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(31)
            sage: F.gen()
            1
        """
        if n > 0:
            raise IndexError, "only one generator"
        return self._cache.gen()

    def prime_subfield(self):
        r"""
        Return the prime subfield $\FF_p$ of self if self is $\FF_{p^n}$.

        EXAMPLES:
            sage: GF(3^4, 'b').prime_subfield()
            Finite Field of size 3

            sage: S.<b> = GF(5^2); S
            Finite Field in b of size 5^2
            sage: S.prime_subfield()
            Finite Field of size 5
            sage: type(S.prime_subfield())
            <class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>
        """
        try:
            return self._prime_subfield
        except AttributeError:
            import constructor
            self._prime_subfield = constructor.FiniteField(self.characteristic())
            return self._prime_subfield

    def log_to_int(self, n):
        r"""
        Given an integer $n$ this method returns $i$ where $i$
        satisfies \code{self.gen()^n == i}, if the result is
        interpreted as an integer.

        INPUT:
            n -- log representation of a finite field element

        OUTPUT:
            integer representation of a finite field element.

        EXAMPLE:
            sage: k = GF(2**8, 'a')
            sage: k.log_to_int(4)
            16
            sage: k.log_to_int(20)
            180
        """
        return self._cache.log_to_int(n)
    
    def int_to_log(self, n):
        r"""
        Given an integer $n$ this method returns $i$ where $i$ satisfies
        \code{self.gen()^i==(n\%self.characteristic())}. 

        INPUT:
            n -- integer representation of an finite field element

        OUTPUT:
            log representation of n

        EXAMPLE:
            sage: k = GF(7**3, 'a')
            sage: k.int_to_log(4)
            228
            sage: k.int_to_log(3)
            57
            sage: k.gen()^57
            3
        """
        return self._cache.int_to_log(n)

    def fetch_int(self, n):
        r"""
        Given an integer $n$ return a finite field element in self
        which equals $n$ under the condition that  self.gen() is set to
        self.characteristic().

        EXAMPLE:
            sage: k.<a> = GF(2^8)
            sage: k.fetch_int(8)
            a^3
            sage: e = k.fetch_int(151); e
            a^7 + a^4 + a^2 + a + 1
            sage: 2^7 + 2^4 + 2^2 + 2 + 1
            151
        """
        return self._cache.fetch_int(n)

    def polynomial(self, name=None):
        """
        Return the defining polynomial of this field as an element of
        self.polynomial_ring().
        
        This is the same as the characteristic polynomial of the
        generator of self.

        INPUT:
            name -- optional name of the generator

        EXAMPLES:
            sage: k = GF(3^4, 'a')
            sage: k.polynomial()
            a^4 + 2*a^3 + 2        
        """
        if name is not None:
            try:
                return self._polynomial
            except AttributeError:
                pass
        quo = (-(self.gen()**(self.degree()))).integer_representation()
        b   = int(self.characteristic())
        
        ret = []
        for i in range(self.degree()):
            ret.append(quo%b)
            quo = quo/b
        ret = ret + [1]
        R = self.polynomial_ring(name)
        if name is None:
            self._polynomial = R(ret)
            return self._polynomial
        else:
            return R(ret)

    def __hash__(self):
        """
        The hash of a Givaro finite field is a hash over it's
        characteristic polynomial and the string 'givaro'.

        EXAMPLES:
            sage: {GF(3^4, 'a'):1} #indirect doctest
            {Finite Field in a of size 3^4: 1}
        """
        try:
            return self._hash
        except AttributeError:
            if self.degree() > 1:
                self._hash = hash((self.characteristic(), self.polynomial(), self.variable_name(), "givaro"))
            else:
                self._hash = hash((self.characteristic(), self.variable_name(), "givaro"))
            return self._hash

    def _pari_modulus(self):
        """
        EXAMPLES:
            sage: GF(3^4,'a')._pari_modulus()
            Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(2, 3)        
        """
        f = pari(str(self.modulus()))
        return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())

    def _finite_field_ext_pari_(self):  # todo -- cache
        """
        Return a FiniteField_ext_pari isomorphic to self with the same
        defining polynomial.

        EXAMPLES:
            sage: GF(3^4,'z')._finite_field_ext_pari_()
            Finite Field in z of size 3^4
        """
        f = self.polynomial()
        import finite_field_ext_pari
        return finite_field_ext_pari.FiniteField_ext_pari(self.order(),
                                                          self.variable_name(), f)

    def __iter__(self):
        """
        Finite fields may be iterated over:

        EXAMPLE:
            sage: list(GF(2**2, 'a'))
            [0, a, a + 1, 1]
        """
        from element_givaro import FiniteField_givaro_iterator
        return FiniteField_givaro_iterator(self._cache)

    def a_times_b_plus_c(self, a, b, c):
        """
        Return r = a*b + c. This is faster than multiplying a and b
        first and adding c to the result.

        INPUT:
            a -- FiniteField_givaroElement
            b -- FiniteField_givaroElement
            c -- FiniteField_givaroElement

        EXAMPLE:
            sage: k.<a> = GF(2**8)
            sage: k.a_times_b_plus_c(a,a,k(1))
            a^2 + 1
        """
        return self._cache.a_times_b_plus_c(a, b, c)

    def a_times_b_minus_c(self, a, b, c):
        """
        Return r = a*b - c.

        INPUT:
            a -- FiniteField_givaroElement
            b -- FiniteField_givaroElement
            c -- FiniteField_givaroElement

        EXAMPLE:
            sage: k.<a> = GF(3**3)
            sage: k.a_times_b_minus_c(a,a,k(1))
            a^2 + 2
        """
        return self._cache.a_times_b_minus_c(a, b, c)

    def c_minus_a_times_b(self, a, b, c):
        """
        Return r = c - a*b. 

        INPUT:
            a -- FiniteField_givaroElement
            b -- FiniteField_givaroElement
            c -- FiniteField_givaroElement

        EXAMPLE:
            sage: k.<a> = GF(3**3)
            sage: k.c_minus_a_times_b(a,a,k(1))
            2*a^2 + 1
        """
        return self._cache.c_minus_a_times_b(a, b, c)
コード例 #13
0
ファイル: finite_field_givaro.py プロジェクト: dagss/sage
    def __init__(self, q, name="a",  modulus=None, repr="poly", cache=False):
        """
        Finite Field. These are implemented using Zech logs and the
        cardinality must be < 2^16. By default conway polynomials are
        used as minimal polynomial.

        INPUT:
            q     -- p^n (must be prime power)
            name  -- variable used for poly_repr (default: 'a')
            modulus -- you may provide a minimal polynomial to use for
                     reduction or 'random' to force a random
                     irreducible polynomial. (default: None, a conway
                     polynomial is used if found. Otherwise a random
                     polynomial is used)
            repr  -- controls the way elements are printed to the user:
                     (default: 'poly')
                     'log': repr is element.log_repr()
                     'int': repr is element.int_repr()
                     'poly': repr is element.poly_repr()
            cache -- if True a cache of all elements of this field is
                     created. Thus, arithmetic does not create new
                     elements which speeds calculations up. Also, if
                     many elements are needed during a calculation
                     this cache reduces the memory requirement as at
                     most self.order() elements are created. (default: False)

        OUTPUT:
            Givaro finite field with characteristic p and cardinality p^n.

        EXAMPLES:

            By default conway polynomials are used:
        
            sage: k.<a> = GF(2**8)
            sage: -a ^ k.degree()
            a^4 + a^3 + a^2 + 1
            sage: f = k.modulus(); f 
            x^8 + x^4 + x^3 + x^2 + 1

            You may enforce a modulus:
            
            sage: P.<x> = PolynomialRing(GF(2))
            sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael Polynomial
            sage: k.<a> = GF(2^8, modulus=f)
            sage: k.modulus()
            x^8 + x^4 + x^3 + x + 1
            sage: a^(2^8)
            a

            You may enforce a random modulus:

            sage: k = GF(3**5, 'a', modulus='random')
            sage: k.modulus() # random polynomial
            x^5 + 2*x^4 + 2*x^3 + x^2 + 2

            Three different representations are possible:
            
            sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='poly').gen()
            a
            sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='int').gen()
            3
            sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='log').gen()
            5

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False
            
            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(j).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError, "Unknown representation %s"%repr

        q = Integer(q)
        if q < 2:
            raise ValueError, "q  must be a prime power"
        F = q.factor()
        if len(F) > 1:
            raise ValueError, "q must be a prime power"
        p = F[0][0]
        k = F[0][1]

        if q >= 1<<16:
            raise ValueError, "q must be < 2^16"

        import constructor
        FiniteField.__init__(self, constructor.FiniteField(p), name, normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        self._is_conway = False
        if modulus is None or modulus == 'conway':
            if k == 1:
                modulus = 'random' # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.constructor import conway_polynomial
                modulus = conway_polynomial(p, k)
                self._is_conway = True
            elif modulus is None:
                modulus = 'random'
            else:
                raise ValueError, "Conway polynomial not found"
                
        from sage.rings.polynomial.all import is_Polynomial
        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
コード例 #14
0
class FiniteField_givaro(FiniteField):
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Finite Field. These are implemented using Zech logs and the
        cardinality must be < 2^16. By default conway polynomials are
        used as minimal polynomial.

        INPUT:
            q     -- p^n (must be prime power)
            name  -- variable used for poly_repr (default: 'a')
            modulus -- you may provide a minimal polynomial to use for
                     reduction or 'random' to force a random
                     irreducible polynomial. (default: None, a conway
                     polynomial is used if found. Otherwise a random
                     polynomial is used)
            repr  -- controls the way elements are printed to the user:
                     (default: 'poly')
                     'log': repr is element.log_repr()
                     'int': repr is element.int_repr()
                     'poly': repr is element.poly_repr()
            cache -- if True a cache of all elements of this field is
                     created. Thus, arithmetic does not create new
                     elements which speeds calculations up. Also, if
                     many elements are needed during a calculation
                     this cache reduces the memory requirement as at
                     most self.order() elements are created. (default: False)

        OUTPUT:
            Givaro finite field with characteristic p and cardinality p^n.

        EXAMPLES:

            By default conway polynomials are used:
        
            sage: k.<a> = GF(2**8)
            sage: -a ^ k.degree()
            a^4 + a^3 + a^2 + 1
            sage: f = k.modulus(); f 
            x^8 + x^4 + x^3 + x^2 + 1

            You may enforce a modulus:
            
            sage: P.<x> = PolynomialRing(GF(2))
            sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael Polynomial
            sage: k.<a> = GF(2^8, modulus=f)
            sage: k.modulus()
            x^8 + x^4 + x^3 + x + 1
            sage: a^(2^8)
            a

            You may enforce a random modulus:

            sage: k = GF(3**5, 'a', modulus='random')
            sage: k.modulus() # random polynomial
            x^5 + 2*x^4 + 2*x^3 + x^2 + 2

            Three different representations are possible:
            
            sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='poly').gen()
            a
            sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='int').gen()
            3
            sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='log').gen()
            5

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False
            
            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(j).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError, "Unknown representation %s" % repr

        q = Integer(q)
        if q < 2:
            raise ValueError, "q  must be a prime power"
        F = q.factor()
        if len(F) > 1:
            raise ValueError, "q must be a prime power"
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError, "q must be < 2^16"

        import constructor
        FiniteField.__init__(self,
                             constructor.FiniteField(p),
                             name,
                             normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        self._is_conway = False
        if modulus is None or modulus == 'conway':
            if k == 1:
                modulus = 'random'  # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.constructor import conway_polynomial
                modulus = conway_polynomial(p, k)
                self._is_conway = True
            elif modulus is None:
                modulus = 'random'
            else:
                raise ValueError, "Conway polynomial not found"

        from sage.rings.polynomial.all import is_Polynomial
        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)

    def characteristic(self):
        """
        Return the characteristic of this field.

        EXAMPLES:
            sage: p = GF(19^5,'a').characteristic(); p
            19
            sage: type(p)
            <type 'sage.rings.integer.Integer'>
        """
        return Integer(self._cache.characteristic())

    def order(self):
        """
        Return the cardinality of this field.

        OUTPUT:
            Integer -- the number of elements in self.

        EXAMPLES:
            sage: n = GF(19^5,'a').order(); n
            2476099
            sage: type(n)
            <type 'sage.rings.integer.Integer'>        
        """
        return self._cache.order()

    def degree(self):
        r"""
        If \code{self.cardinality() == p^n} this method returns $n$.

        OUTPUT:
            Integer -- the degree

        EXAMPLES:
            sage: GF(3^4,'a').degree()
            4
        """
        return Integer(self._cache.exponent())

    def is_atomic_repr(self):
        """
        Return whether elements of self are printed using an atomic
        representation.
        
        EXAMPLES:
            sage: GF(3^4,'a').is_atomic_repr()
            False        
        """
        if self._cache.repr == 0:  #modulus
            return False
        else:
            return True

    def random_element(self, *args, **kwds):
        """
        Return a random element of self.

        INPUT:
            *args -- ignored
            **kwds -- ignored

        EXAMPLES:
            sage: k = GF(23**3, 'a')
            sage: e = k.random_element(); e
            9*a^2 + 10*a + 3
            sage: type(e)
            <type 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>

            sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))
            sage: P.random_element(5)
            a^2 + 2*a + 1 + (a + 1)*x + (a^2 + a + 1)*x^2 + (a^2 + 1)*x^3 + (2*a^2 + a)*x^4 + O(x^5)
        """
        return self._cache.random_element()

    def _element_constructor_(self, e):
        """
        Coerces several data types to self.

        INPUT:
        
        e -- data to coerce

        EXAMPLES:

        FiniteField_givaroElement are accepted where the parent
        is either self, equals self or is the prime subfield::
        
            sage: k = GF(2**8, 'a')
            sage: k.gen() == k(k.gen())
            True

        Floats, ints, longs, Integer are interpreted modulo characteristic::
            
            sage: k(2) # indirect doctest
            0

            Floats coerce in:
            sage: k(float(2.0))
            0
            
        Rational are interpreted as self(numerator)/self(denominator).
        Both may not be >= self.characteristic().
        ::

            sage: k = GF(3**8, 'a')
            sage: k(1/2) == k(1)/k(2)
            True

        Free module elements over self.prime_subfield() are interpreted 'little endian'::
            
            sage: k = GF(2**8, 'a')
            sage: e = k.vector_space().gen(1); e
            (0, 1, 0, 0, 0, 0, 0, 0)
            sage: k(e)
            a

        'None' yields zero::

            sage: k(None)
            0

        Strings are evaluated as polynomial representation of elements in self::

            sage: k('a^2+1')
            a^2 + 1

        Univariate polynomials coerce into finite fields by evaluating
        the polynomial at the field's generator::

            sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
            sage: R.<x> = QQ[]
            sage: k, a = FiniteField_givaro(5^2, 'a').objgen()
            sage: k(R(2/3))
            4
            sage: k(x^2)
            a + 3
            sage: R.<x> = GF(5)[]
            sage: k(x^3-2*x+1)
            2*a + 4

            sage: x = polygen(QQ)
            sage: k(x^25)
            a

            sage: Q, q = FiniteField_givaro(5^3,'q').objgen()
            sage: L = GF(5)
            sage: LL.<xx> = L[]
            sage: Q(xx^2 + 2*xx + 4)
            q^2 + 2*q + 4


        Multivariate polynomials only coerce if constant::

            sage: R = k['x,y,z']; R
            Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2
            sage: k(R(2))
            2
            sage: R = QQ['x,y,z']
            sage: k(R(1/5))
            Traceback (most recent call last):
            ...
            ZeroDivisionError: division by zero in finite field.

        
        PARI elements are interpreted as finite field elements; this PARI flexibility
        is (absurdly!) liberal::

            sage: k = GF(2**8, 'a')
            sage: k(pari('Mod(1,2)'))
            1
            sage: k(pari('Mod(2,3)'))
            0
            sage: k(pari('Mod(1,3)*a^20'))
            a^7 + a^5 + a^4 + a^2

        GAP elements need to be finite field elements::

            sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
            sage: x = gap('Z(13)')
            sage: F = FiniteField_givaro(13)
            sage: F(x)
            2
            sage: F(gap('0*Z(13)'))
            0
            sage: F = FiniteField_givaro(13^2)
            sage: x = gap('Z(13)')
            sage: F(x)
            2
            sage: x = gap('Z(13^2)^3')
            sage: F(x)
            12*a + 11
            sage: F.multiplicative_generator()^3
            12*a + 11

            sage: k.<a> = GF(29^3)
            sage: k(48771/1225)
            28

            sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
            sage: F9 = FiniteField_givaro(9)
            sage: F81 = FiniteField_givaro(81)
            sage: F81(F9.gen())
            Traceback (most recent call last):
            ...
            TypeError: unable to coerce from a finite field other than the prime subfield
        """
        return self._cache.element_from_data(e)

    def _coerce_map_from_(self, R):
        """
        Returns True if this finite field has a coercion map from R.

        EXAMPLES::

            sage: k.<a> = GF(3^8)
            sage: a + 1 # indirect doctest
            a + 1
            sage: a + int(1)
            a + 1
            sage: a + GF(3)(1)
            a + 1
        """
        from sage.rings.integer_ring import ZZ
        from sage.rings.finite_rings.finite_field_base import is_FiniteField
        from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic
        if R is int or R is long or R is ZZ:
            return True
        if is_FiniteField(R):
            if R is self:
                return True
            from sage.rings.residue_field import ResidueField_generic
            if isinstance(R, ResidueField_generic):
                return False
            if R.characteristic() == self.characteristic():
                if isinstance(R, IntegerModRing_generic):
                    return True
                if R.degree() == 1:
                    return True
                elif self.degree() % R.degree() == 0:
                    # This is where we *would* do coercion from one nontrivial finite field to another...
                    # We use this error message for backward compatibility until #8335 is finished
                    raise TypeError, "unable to coerce from a finite field other than the prime subfield"

    def gen(self, n=0):
        r"""
        Return a generator of self. All elements x of self are
        expressed as $\log_{self.gen()}(p)$ internally.

        This generator might differ between different runs or
        different architectures.

        WARNING: The generator is not guaranteed to be a generator for
            the multiplicative group.  To obtain the latter, use
            multiplicative_generator().

        EXAMPLES:
            sage: k = GF(3^4, 'b'); k.gen()
            b
            sage: k.gen(1)
            Traceback (most recent call last):
            ...
            IndexError: only one generator
            sage: F = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(31)
            sage: F.gen()
            1
        """
        if n > 0:
            raise IndexError, "only one generator"
        return self._cache.gen()

    def prime_subfield(self):
        r"""
        Return the prime subfield $\FF_p$ of self if self is $\FF_{p^n}$.

        EXAMPLES:
            sage: GF(3^4, 'b').prime_subfield()
            Finite Field of size 3

            sage: S.<b> = GF(5^2); S
            Finite Field in b of size 5^2
            sage: S.prime_subfield()
            Finite Field of size 5
            sage: type(S.prime_subfield())
            <class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>
        """
        try:
            return self._prime_subfield
        except AttributeError:
            import constructor
            self._prime_subfield = constructor.FiniteField(
                self.characteristic())
            return self._prime_subfield

    def log_to_int(self, n):
        r"""
        Given an integer $n$ this method returns $i$ where $i$
        satisfies \code{self.gen()^n == i}, if the result is
        interpreted as an integer.

        INPUT:
            n -- log representation of a finite field element

        OUTPUT:
            integer representation of a finite field element.

        EXAMPLE:
            sage: k = GF(2**8, 'a')
            sage: k.log_to_int(4)
            16
            sage: k.log_to_int(20)
            180
        """
        return self._cache.log_to_int(n)

    def int_to_log(self, n):
        r"""
        Given an integer $n$ this method returns $i$ where $i$ satisfies
        \code{self.gen()^i==(n\%self.characteristic())}. 

        INPUT:
            n -- integer representation of an finite field element

        OUTPUT:
            log representation of n

        EXAMPLE:
            sage: k = GF(7**3, 'a')
            sage: k.int_to_log(4)
            228
            sage: k.int_to_log(3)
            57
            sage: k.gen()^57
            3
        """
        return self._cache.int_to_log(n)

    def fetch_int(self, n):
        r"""
        Given an integer $n$ return a finite field element in self
        which equals $n$ under the condition that  self.gen() is set to
        self.characteristic().

        EXAMPLE:
            sage: k.<a> = GF(2^8)
            sage: k.fetch_int(8)
            a^3
            sage: e = k.fetch_int(151); e
            a^7 + a^4 + a^2 + a + 1
            sage: 2^7 + 2^4 + 2^2 + 2 + 1
            151
        """
        return self._cache.fetch_int(n)

    def polynomial(self, name=None):
        """
        Return the defining polynomial of this field as an element of
        self.polynomial_ring().
        
        This is the same as the characteristic polynomial of the
        generator of self.

        INPUT:
            name -- optional name of the generator

        EXAMPLES:
            sage: k = GF(3^4, 'a')
            sage: k.polynomial()
            a^4 + 2*a^3 + 2        
        """
        if name is not None:
            try:
                return self._polynomial
            except AttributeError:
                pass
        quo = (-(self.gen()**(self.degree()))).integer_representation()
        b = int(self.characteristic())

        ret = []
        for i in range(self.degree()):
            ret.append(quo % b)
            quo = quo / b
        ret = ret + [1]
        R = self.polynomial_ring(name)
        if name is None:
            self._polynomial = R(ret)
            return self._polynomial
        else:
            return R(ret)

    def __hash__(self):
        """
        The hash of a Givaro finite field is a hash over it's
        characteristic polynomial and the string 'givaro'.

        EXAMPLES:
            sage: {GF(3^4, 'a'):1} #indirect doctest
            {Finite Field in a of size 3^4: 1}
        """
        try:
            return self._hash
        except AttributeError:
            if self.degree() > 1:
                self._hash = hash((self.characteristic(), self.polynomial(),
                                   self.variable_name(), "givaro"))
            else:
                self._hash = hash(
                    (self.characteristic(), self.variable_name(), "givaro"))
            return self._hash

    def _pari_modulus(self):
        """
        EXAMPLES:
            sage: GF(3^4,'a')._pari_modulus()
            Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(2, 3)        
        """
        f = pari(str(self.modulus()))
        return f.subst('x', 'a') * pari("Mod(1,%s)" % self.characteristic())

    def _finite_field_ext_pari_(self):  # todo -- cache
        """
        Return a FiniteField_ext_pari isomorphic to self with the same
        defining polynomial.

        EXAMPLES:
            sage: GF(3^4,'z')._finite_field_ext_pari_()
            Finite Field in z of size 3^4
        """
        f = self.polynomial()
        import finite_field_ext_pari
        return finite_field_ext_pari.FiniteField_ext_pari(
            self.order(), self.variable_name(), f)

    def __iter__(self):
        """
        Finite fields may be iterated over:

        EXAMPLE:
            sage: list(GF(2**2, 'a'))
            [0, a, a + 1, 1]
        """
        from element_givaro import FiniteField_givaro_iterator
        return FiniteField_givaro_iterator(self._cache)

    def a_times_b_plus_c(self, a, b, c):
        """
        Return r = a*b + c. This is faster than multiplying a and b
        first and adding c to the result.

        INPUT:
            a -- FiniteField_givaroElement
            b -- FiniteField_givaroElement
            c -- FiniteField_givaroElement

        EXAMPLE:
            sage: k.<a> = GF(2**8)
            sage: k.a_times_b_plus_c(a,a,k(1))
            a^2 + 1
        """
        return self._cache.a_times_b_plus_c(a, b, c)

    def a_times_b_minus_c(self, a, b, c):
        """
        Return r = a*b - c.

        INPUT:
            a -- FiniteField_givaroElement
            b -- FiniteField_givaroElement
            c -- FiniteField_givaroElement

        EXAMPLE:
            sage: k.<a> = GF(3**3)
            sage: k.a_times_b_minus_c(a,a,k(1))
            a^2 + 2
        """
        return self._cache.a_times_b_minus_c(a, b, c)

    def c_minus_a_times_b(self, a, b, c):
        """
        Return r = c - a*b. 

        INPUT:
            a -- FiniteField_givaroElement
            b -- FiniteField_givaroElement
            c -- FiniteField_givaroElement

        EXAMPLE:
            sage: k.<a> = GF(3**3)
            sage: k.c_minus_a_times_b(a,a,k(1))
            2*a^2 + 1
        """
        return self._cache.c_minus_a_times_b(a, b, c)
コード例 #15
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Finite Field. These are implemented using Zech logs and the
        cardinality must be < 2^16. By default conway polynomials are
        used as minimal polynomial.

        INPUT:
            q     -- p^n (must be prime power)
            name  -- variable used for poly_repr (default: 'a')
            modulus -- you may provide a minimal polynomial to use for
                     reduction or 'random' to force a random
                     irreducible polynomial. (default: None, a conway
                     polynomial is used if found. Otherwise a random
                     polynomial is used)
            repr  -- controls the way elements are printed to the user:
                     (default: 'poly')
                     'log': repr is element.log_repr()
                     'int': repr is element.int_repr()
                     'poly': repr is element.poly_repr()
            cache -- if True a cache of all elements of this field is
                     created. Thus, arithmetic does not create new
                     elements which speeds calculations up. Also, if
                     many elements are needed during a calculation
                     this cache reduces the memory requirement as at
                     most self.order() elements are created. (default: False)

        OUTPUT:
            Givaro finite field with characteristic p and cardinality p^n.

        EXAMPLES:

            By default conway polynomials are used:
        
            sage: k.<a> = GF(2**8)
            sage: -a ^ k.degree()
            a^4 + a^3 + a^2 + 1
            sage: f = k.modulus(); f 
            x^8 + x^4 + x^3 + x^2 + 1

            You may enforce a modulus:
            
            sage: P.<x> = PolynomialRing(GF(2))
            sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael Polynomial
            sage: k.<a> = GF(2^8, modulus=f)
            sage: k.modulus()
            x^8 + x^4 + x^3 + x + 1
            sage: a^(2^8)
            a

            You may enforce a random modulus:

            sage: k = GF(3**5, 'a', modulus='random')
            sage: k.modulus() # random polynomial
            x^5 + 2*x^4 + 2*x^3 + x^2 + 2

            Three different representations are possible:
            
            sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='poly').gen()
            a
            sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='int').gen()
            3
            sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='log').gen()
            5

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False
            
            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(j).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError, "Unknown representation %s" % repr

        q = Integer(q)
        if q < 2:
            raise ValueError, "q  must be a prime power"
        F = q.factor()
        if len(F) > 1:
            raise ValueError, "q must be a prime power"
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError, "q must be < 2^16"

        import constructor
        FiniteField.__init__(self,
                             constructor.FiniteField(p),
                             name,
                             normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        self._is_conway = False
        if modulus is None or modulus == 'conway':
            if k == 1:
                modulus = 'random'  # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.constructor import conway_polynomial
                modulus = conway_polynomial(p, k)
                self._is_conway = True
            elif modulus is None:
                modulus = 'random'
            else:
                raise ValueError, "Conway polynomial not found"

        from sage.rings.polynomial.all import is_Polynomial
        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)