Exemple #1
0
def pinch_method(p, n, m, f = None, g = None):
    '''
    Function that given three integers p, n and m such as :

    - p is prime,
    - m is dividing n and there exists a primitive mth root that spans F_{p^n} 
    and none of its subfields,

    returns the image, in a finite field G, of the polynomial generator of a 
    finite field F with the same cardinality as G.
    '''
    c, w = cputime(), walltime()
    R = PolynomialRing(GF(p), 'X')

    # If no polynomials are given, we compute both of them randomly.
    if f is None:
        f = R.irreducible_element(n, algorithm='random')
    if g is None:
        g = R.irreducible_element(n, algorithm='random')
    while f == g:
        g = R.irreductible_element(n, algorithm='random')

    # We compute two fields of cardinality p^n and two primitive m-rooth
    rootmf, rootmg, F, G = find_mroots_and_fields(p, n, m, f, g)

    # The matrixes will contain the coefficients of rootmf and rootmg in the 
    # basis x^i and y^i respectively
    A = matrix(GF(p), n, n)
    B = matrix(GF(p), n, n)

    for i in range(n):
    	A[i,:] = (rootmf**i).vector()

    # Failsafe, but probably outdated
    try:
    	Ainv = A.inverse()
    except ZeroDivisionError:
    	print 'erreur'
        return A

    # We will try to find the power s such as phi(rootmf) = rootmg^s, since 
    # rootmg and rootmf are both primitive mrooth it is bound to happen 
    # since the multiplicative group is cyclic.
    s = 1	


    while s <= m :	
    	for i in range(n):
		B[i,:] = ((rootmg**s)**i).vector()


        # This will be the isomorphism's matrix
    	C = Ainv*B	

    	v = C[1,:]	  # The second line correponds to the image of x
        res = G(v[0])

	# I realized that you could try to find if the image of 
	# rootmf is also a zero of the minimal polynomial of rootmf 
	# but it would force us to compute yet another minimal polynomials.
	# Instead, if you find that the image of x is a root of f, 
	# then you win!
        if f(res) == 0:
	    	print 'CPU %s, Wall %s' % (cputime(c), walltime(w))
	    	# Some of what is returned is probably useless and only here 
	    	# for testing purposes.
	    	return (res, C, rootmf, rootmg, s, f, F, G)

    	s = s + 1
	
    print 'No isomorphism found, check your m.'
    return 1
Exemple #2
0
    def create_key_and_extra_args(self,
                                  order,
                                  name=None,
                                  modulus=None,
                                  names=None,
                                  impl=None,
                                  proof=None,
                                  check_irreducible=True,
                                  prefix=None,
                                  repr=None,
                                  elem_cache=None,
                                  **kwds):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', 3, 2, True, None, 'poly', True), {})

        We do not take invalid keyword arguments and raise a value error
        to better ensure uniqueness::

            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            Traceback (most recent call last):
            ...
            TypeError: create_key_and_extra_args() got an unexpected keyword argument 'foo'

        Moreover, ``repr`` and ``elem_cache`` are ignored when not
        using givaro::

            sage: GF.create_key_and_extra_args(16, 'a', impl='ntl', repr='poly')
            ((16, ('a',), x^4 + x + 1, 'ntl', 2, 4, True, None, None, None), {})
            sage: GF.create_key_and_extra_args(16, 'a', impl='ntl', elem_cache=False)
            ((16, ('a',), x^4 + x + 1, 'ntl', 2, 4, True, None, None, None), {})
            sage: GF(16, impl='ntl') is GF(16, impl='ntl', repr='foo')
            True

        We handle extra arguments for the givaro finite field and
        create unique objects for their defaults::

            sage: GF(25, impl='givaro') is GF(25, impl='givaro', repr='poly')
            True
            sage: GF(25, impl='givaro') is GF(25, impl='givaro', elem_cache=True)
            True
            sage: GF(625, impl='givaro') is GF(625, impl='givaro', elem_cache=False)
            True

        We explicitly take ``structure``, ``implementation`` and ``prec`` attributes
        for compatibility with :class:`~sage.categories.pushout.AlgebraicExtensionFunctor`
        but we ignore them as they are not used, see :trac:`21433`::

            sage: GF.create_key_and_extra_args(9, 'a', structure=None)
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', 3, 2, True, None, 'poly', True), {})
        """
        import sage.arith.all
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None:
            proof = arithmetic()
        for key, val in kwds.items():
            if key not in ['structure', 'implementation', 'prec', 'embedding']:
                raise TypeError(
                    "create_key_and_extra_args() got an unexpected keyword argument '%s'"
                    % key)
            if not (val is None
                    or isinstance(val, list) and all(c is None for c in val)):
                raise NotImplementedError(
                    "ring extension with prescribed %s is not implemented" %
                    key)
        with WithProof('arithmetic', proof):
            order = Integer(order)
            if order <= 1:
                raise ValueError(
                    "the order of a finite field must be at least 2")

            if order.is_prime():
                p = order
                n = Integer(1)
                if impl is None:
                    impl = 'modn'
                name = ('x', )  # Ignore name
                # Every polynomial of degree 1 is irreducible
                check_irreducible = False
            elif order.is_prime_power():
                if names is not None:
                    name = names
                if name is not None:
                    name = normalize_names(1, name)

                p, n = order.factor()[0]
                if name is None:
                    if prefix is None:
                        prefix = 'z'
                    name = prefix + str(n)
                    if modulus is not None:
                        raise ValueError(
                            "no modulus may be specified if variable name not given"
                        )
                    # Fpbar will have a strong reference, since algebraic_closure caches its results,
                    # and the coefficients of modulus lie in GF(p)
                    Fpbar = GF(p).algebraic_closure(prefix)
                    # This will give a Conway polynomial if p,n is small enough to be in the database
                    # and a pseudo-Conway polynomial if it's not.
                    modulus = Fpbar._get_polynomial(n)
                    check_irreducible = False

                if impl is None:
                    if order < zech_log_bound:
                        impl = 'givaro'
                    elif p == 2:
                        impl = 'ntl'
                    else:
                        impl = 'pari_ffelt'
            else:
                raise ValueError(
                    "the order of a finite field must be a prime power")

            # Determine modulus.
            # For the 'modn' implementation, we use the following
            # optimization which we also need to avoid an infinite loop:
            # a modulus of None is a shorthand for x-1.
            if modulus is not None or impl != 'modn':
                R = PolynomialRing(FiniteField(p), 'x')
                if modulus is None:
                    modulus = R.irreducible_element(n)
                if isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    modulus = R.irreducible_element(n, algorithm=modulus)
                else:
                    if sage.rings.polynomial.polynomial_element.is_Polynomial(
                            modulus):
                        modulus = modulus.change_variable_name('x')
                    modulus = R(modulus).monic()

                    if modulus.degree() != n:
                        raise ValueError(
                            "the degree of the modulus does not equal the degree of the field"
                        )
                    if check_irreducible and not modulus.is_irreducible():
                        raise ValueError(
                            "finite field modulus must be irreducible but it is not"
                        )
                # If modulus is x - 1 for impl="modn", set it to None
                if impl == 'modn' and modulus[0] == -1:
                    modulus = None

            # Check extra arguments for givaro and setup their defaults
            # TODO: ntl takes a repr, but ignores it
            if impl == 'givaro':
                if repr is None:
                    repr = 'poly'
                if elem_cache is None:
                    elem_cache = (order < 500)
            else:
                # This has the effect of ignoring these keywords
                repr = None
                elem_cache = None

            return (order, name, modulus, impl, p, n, proof, prefix, repr,
                    elem_cache), {}
    def create_key_and_extra_args(self, order, name=None, modulus=None, names=None,
                                  impl=None, proof=None, check_irreducible=True,
                                  prefix=None, repr=None, elem_cache=None,
                                  structure=None):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', 3, 2, True, None, 'poly', True), {})

        We do not take invalid keyword arguments and raise a value error
        to better ensure uniqueness::

            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            Traceback (most recent call last):
            ...
            TypeError: create_key_and_extra_args() got an unexpected keyword argument 'foo'

        Moreover, ``repr`` and ``elem_cache`` are ignored when not
        using givaro::

            sage: GF.create_key_and_extra_args(16, 'a', impl='ntl', repr='poly')
            ((16, ('a',), x^4 + x + 1, 'ntl', 2, 4, True, None, None, None), {})
            sage: GF.create_key_and_extra_args(16, 'a', impl='ntl', elem_cache=False)
            ((16, ('a',), x^4 + x + 1, 'ntl', 2, 4, True, None, None, None), {})
            sage: GF(16, impl='ntl') is GF(16, impl='ntl', repr='foo')
            True

        We handle extra arguments for the givaro finite field and
        create unique objects for their defaults::

            sage: GF(25, impl='givaro') is GF(25, impl='givaro', repr='poly')
            True
            sage: GF(25, impl='givaro') is GF(25, impl='givaro', elem_cache=True)
            True
            sage: GF(625, impl='givaro') is GF(625, impl='givaro', elem_cache=False)
            True

        We explicitly take a ``structure`` attribute for compatibility
        with :class:`~sage.categories.pushout.AlgebraicExtensionFunctor`
        but we ignore it as it is not used, see :trac:`21433`::

            sage: GF.create_key_and_extra_args(9, 'a', structure=None)
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', 3, 2, True, None, 'poly', True), {})
        """
        import sage.arith.all
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None:
            proof = arithmetic()
        with WithProof('arithmetic', proof):
            order = Integer(order)
            if order <= 1:
                raise ValueError("the order of a finite field must be at least 2")

            if order.is_prime():
                p = order
                n = Integer(1)
                if impl is None:
                    impl = 'modn'
                name = ('x',)  # Ignore name
                # Every polynomial of degree 1 is irreducible
                check_irreducible = False
            elif order.is_prime_power():
                if names is not None:
                    name = names
                if name is not None:
                    name = normalize_names(1, name)

                p, n = order.factor()[0]
                if name is None:
                    if prefix is None:
                        prefix = 'z'
                    name = prefix + str(n)
                    if modulus is not None:
                        raise ValueError("no modulus may be specified if variable name not given")
                    # Fpbar will have a strong reference, since algebraic_closure caches its results,
                    # and the coefficients of modulus lie in GF(p)
                    Fpbar = GF(p).algebraic_closure(prefix)
                    # This will give a Conway polynomial if p,n is small enough to be in the database
                    # and a pseudo-Conway polynomial if it's not.
                    modulus = Fpbar._get_polynomial(n)
                    check_irreducible = False

                if impl is None:
                    if order < zech_log_bound:
                        impl = 'givaro'
                    elif p == 2:
                        impl = 'ntl'
                    else:
                        impl = 'pari_ffelt'
            else:
                raise ValueError("the order of a finite field must be a prime power")

            # Determine modulus.
            # For the 'modn' implementation, we use the following
            # optimization which we also need to avoid an infinite loop:
            # a modulus of None is a shorthand for x-1.
            if modulus is not None or impl != 'modn':
                R = PolynomialRing(FiniteField(p), 'x')
                if modulus is None:
                    modulus = R.irreducible_element(n)
                if isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus == "default":
                        from sage.misc.superseded import deprecation
                        deprecation(16983, "the modulus 'default' is deprecated, use modulus=None instead (which is the default)")
                        modulus = None
                    modulus = R.irreducible_element(n, algorithm=modulus)
                else:
                    if sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
                        modulus = modulus.change_variable_name('x')
                    modulus = R(modulus).monic()

                    if modulus.degree() != n:
                        raise ValueError("the degree of the modulus does not equal the degree of the field")
                    if check_irreducible and not modulus.is_irreducible():
                        raise ValueError("finite field modulus must be irreducible but it is not")
                # If modulus is x - 1 for impl="modn", set it to None
                if impl == 'modn' and modulus[0] == -1:
                    modulus = None

            # Check extra arguments for givaro and setup their defaults
            # TODO: ntl takes a repr, but ignores it
            if impl == 'givaro':
                if repr is None:
                    repr = 'poly'
                if elem_cache is None:
                    elem_cache = (order < 500)
            else:
                # This has the effect of ignoring these keywords
                repr = None
                elem_cache = None

            return (order, name, modulus, impl, p, n, proof, prefix, repr, elem_cache), {}
Exemple #4
0
    def create_key_and_extra_args(self,
                                  order,
                                  name=None,
                                  modulus=None,
                                  names=None,
                                  impl=None,
                                  proof=None,
                                  check_irreducible=True,
                                  **kwds):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', '{}', 3, 2, True), {})
            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})
        """
        import sage.arith.all
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None:
            proof = arithmetic()
        with WithProof('arithmetic', proof):
            order = Integer(order)
            if order <= 1:
                raise ValueError(
                    "the order of a finite field must be at least 2")

            if order.is_prime():
                p = order
                n = Integer(1)
                if impl is None:
                    impl = 'modn'
                name = ('x', )  # Ignore name
                # Every polynomial of degree 1 is irreducible
                check_irreducible = False
            elif order.is_prime_power():
                if names is not None:
                    name = names
                if name is not None:
                    name = normalize_names(1, name)

                p, n = order.factor()[0]

                # The following is a temporary solution that allows us
                # to construct compatible systems of finite fields
                # until algebraic closures of finite fields are
                # implemented in Sage.  It requires the user to
                # specify two parameters:
                #
                # - `conway` -- boolean; if True, this field is
                #   constructed to fit in a compatible system using
                #   a Conway polynomial.
                # - `prefix` -- a string used to generate names for
                #   automatically constructed finite fields
                #
                # See the docstring of FiniteFieldFactory for examples.
                #
                # Once algebraic closures of finite fields are
                # implemented, this syntax should be superseded by
                # something like the following:
                #
                #     sage: Fpbar = GF(5).algebraic_closure('z')
                #     sage: F, e = Fpbar.subfield(3)  # e is the embedding into Fpbar
                #     sage: F
                #     Finite field in z3 of size 5^3
                #
                # This temporary solution only uses actual Conway
                # polynomials (no pseudo-Conway polynomials), since
                # pseudo-Conway polynomials are not unique, and until
                # we have algebraic closures of finite fields, there
                # is no good place to store a specific choice of
                # pseudo-Conway polynomials.
                if name is None:
                    if not ('conway' in kwds and kwds['conway']):
                        raise ValueError(
                            "parameter 'conway' is required if no name given")
                    if 'prefix' not in kwds:
                        raise ValueError(
                            "parameter 'prefix' is required if no name given")
                    name = kwds['prefix'] + str(n)

                if 'conway' in kwds and kwds['conway']:
                    from conway_polynomials import conway_polynomial
                    if 'prefix' not in kwds:
                        raise ValueError(
                            "a prefix must be specified if conway=True")
                    if modulus is not None:
                        raise ValueError(
                            "no modulus may be specified if conway=True")
                    # The following raises a RuntimeError if no polynomial is found.
                    modulus = conway_polynomial(p, n)

                if impl is None:
                    if order < zech_log_bound:
                        impl = 'givaro'
                    elif p == 2:
                        impl = 'ntl'
                    else:
                        impl = 'pari_ffelt'
            else:
                raise ValueError(
                    "the order of a finite field must be a prime power")

            # Determine modulus.
            # For the 'modn' implementation, we use the following
            # optimization which we also need to avoid an infinite loop:
            # a modulus of None is a shorthand for x-1.
            if modulus is not None or impl != 'modn':
                R = PolynomialRing(FiniteField(p), 'x')
                if modulus is None:
                    modulus = R.irreducible_element(n)
                if isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus == "default":
                        from sage.misc.superseded import deprecation
                        deprecation(
                            16983,
                            "the modulus 'default' is deprecated, use modulus=None instead (which is the default)"
                        )
                        modulus = None
                    modulus = R.irreducible_element(n, algorithm=modulus)
                else:
                    if sage.rings.polynomial.polynomial_element.is_Polynomial(
                            modulus):
                        modulus = modulus.change_variable_name('x')
                    modulus = R(modulus).monic()

                    if modulus.degree() != n:
                        raise ValueError(
                            "the degree of the modulus does not equal the degree of the field"
                        )
                    if check_irreducible and not modulus.is_irreducible():
                        raise ValueError(
                            "finite field modulus must be irreducible but it is not"
                        )
                # If modulus is x - 1 for impl="modn", set it to None
                if impl == 'modn' and modulus[0] == -1:
                    modulus = None

            return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
    def create_key_and_extra_args(
        self, order, name=None, modulus=None, names=None, impl=None, proof=None, check_irreducible=True, **kwds
    ):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', '{}', 3, 2, True), {})
            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})
        """
        import sage.arith.all
        from sage.structure.proof.all import WithProof, arithmetic

        if proof is None:
            proof = arithmetic()
        with WithProof("arithmetic", proof):
            order = Integer(order)
            if order <= 1:
                raise ValueError("the order of a finite field must be at least 2")

            if order.is_prime():
                p = order
                n = Integer(1)
                if impl is None:
                    impl = "modn"
                name = ("x",)  # Ignore name
                # Every polynomial of degree 1 is irreducible
                check_irreducible = False
            elif order.is_prime_power():
                if names is not None:
                    name = names
                if name is not None:
                    name = normalize_names(1, name)

                p, n = order.factor()[0]
                if name is None:
                    if "prefix" not in kwds:
                        kwds["prefix"] = "z"
                    name = kwds["prefix"] + str(n)
                    if modulus is not None:
                        raise ValueError("no modulus may be specified if variable name not given")
                    if "conway" in kwds:
                        del kwds["conway"]
                        from sage.misc.superseded import deprecation

                        deprecation(
                            17569,
                            "the 'conway' argument is deprecated, pseudo-conway polynomials are now used by default if no variable name is given",
                        )
                    # Fpbar will have a strong reference, since algebraic_closure caches its results,
                    # and the coefficients of modulus lie in GF(p)
                    Fpbar = GF(p).algebraic_closure(kwds.get("prefix", "z"))
                    # This will give a Conway polynomial if p,n is small enough to be in the database
                    # and a pseudo-Conway polynomial if it's not.
                    modulus = Fpbar._get_polynomial(n)
                    check_irreducible = False

                if impl is None:
                    if order < zech_log_bound:
                        impl = "givaro"
                    elif p == 2:
                        impl = "ntl"
                    else:
                        impl = "pari_ffelt"
            else:
                raise ValueError("the order of a finite field must be a prime power")

            # Determine modulus.
            # For the 'modn' implementation, we use the following
            # optimization which we also need to avoid an infinite loop:
            # a modulus of None is a shorthand for x-1.
            if modulus is not None or impl != "modn":
                R = PolynomialRing(FiniteField(p), "x")
                if modulus is None:
                    modulus = R.irreducible_element(n)
                if isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus == "default":
                        from sage.misc.superseded import deprecation

                        deprecation(
                            16983,
                            "the modulus 'default' is deprecated, use modulus=None instead (which is the default)",
                        )
                        modulus = None
                    modulus = R.irreducible_element(n, algorithm=modulus)
                else:
                    if sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
                        modulus = modulus.change_variable_name("x")
                    modulus = R(modulus).monic()

                    if modulus.degree() != n:
                        raise ValueError("the degree of the modulus does not equal the degree of the field")
                    if check_irreducible and not modulus.is_irreducible():
                        raise ValueError("finite field modulus must be irreducible but it is not")
                # If modulus is x - 1 for impl="modn", set it to None
                if impl == "modn" and modulus[0] == -1:
                    modulus = None

            return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
    def create_key_and_extra_args(self,
                                  order,
                                  name=None,
                                  modulus=None,
                                  names=None,
                                  impl=None,
                                  proof=None,
                                  check_irreducible=True,
                                  **kwds):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', '{}', 3, 2, True), {})
            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})
        """
        import sage.arith.all
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None:
            proof = arithmetic()
        with WithProof('arithmetic', proof):
            order = Integer(order)
            if order <= 1:
                raise ValueError(
                    "the order of a finite field must be at least 2")

            if order.is_prime():
                p = order
                n = Integer(1)
                if impl is None:
                    impl = 'modn'
                name = ('x', )  # Ignore name
                # Every polynomial of degree 1 is irreducible
                check_irreducible = False
            elif order.is_prime_power():
                if names is not None:
                    name = names
                if name is not None:
                    name = normalize_names(1, name)

                p, n = order.factor()[0]
                if name is None:
                    if 'prefix' not in kwds:
                        kwds['prefix'] = 'z'
                    name = kwds['prefix'] + str(n)
                    if modulus is not None:
                        raise ValueError(
                            "no modulus may be specified if variable name not given"
                        )
                    if 'conway' in kwds:
                        del kwds['conway']
                        from sage.misc.superseded import deprecation
                        deprecation(
                            17569,
                            "the 'conway' argument is deprecated, pseudo-conway polynomials are now used by default if no variable name is given"
                        )
                    # Fpbar will have a strong reference, since algebraic_closure caches its results,
                    # and the coefficients of modulus lie in GF(p)
                    Fpbar = GF(p).algebraic_closure(kwds.get('prefix', 'z'))
                    # This will give a Conway polynomial if p,n is small enough to be in the database
                    # and a pseudo-Conway polynomial if it's not.
                    modulus = Fpbar._get_polynomial(n)
                    check_irreducible = False

                if impl is None:
                    if order < zech_log_bound:
                        impl = 'givaro'
                    elif p == 2:
                        impl = 'ntl'
                    else:
                        impl = 'pari_ffelt'
            else:
                raise ValueError(
                    "the order of a finite field must be a prime power")

            # Determine modulus.
            # For the 'modn' implementation, we use the following
            # optimization which we also need to avoid an infinite loop:
            # a modulus of None is a shorthand for x-1.
            if modulus is not None or impl != 'modn':
                R = PolynomialRing(FiniteField(p), 'x')
                if modulus is None:
                    modulus = R.irreducible_element(n)
                if isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus == "default":
                        from sage.misc.superseded import deprecation
                        deprecation(
                            16983,
                            "the modulus 'default' is deprecated, use modulus=None instead (which is the default)"
                        )
                        modulus = None
                    modulus = R.irreducible_element(n, algorithm=modulus)
                else:
                    if sage.rings.polynomial.polynomial_element.is_Polynomial(
                            modulus):
                        modulus = modulus.change_variable_name('x')
                    modulus = R(modulus).monic()

                    if modulus.degree() != n:
                        raise ValueError(
                            "the degree of the modulus does not equal the degree of the field"
                        )
                    if check_irreducible and not modulus.is_irreducible():
                        raise ValueError(
                            "finite field modulus must be irreducible but it is not"
                        )
                # If modulus is x - 1 for impl="modn", set it to None
                if impl == 'modn' and modulus[0] == -1:
                    modulus = None

            return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
Exemple #7
0
    def create_key_and_extra_args(self, order, name=None, modulus=None, names=None,
                                  impl=None, proof=None, check_irreducible=True, **kwds):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', '{}', 3, 2, True), {})
            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})
        """
        import sage.rings.arith
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None:
            proof = arithmetic()
        with WithProof('arithmetic', proof):
            order = Integer(order)
            if order <= 1:
                raise ValueError("the order of a finite field must be at least 2")

            if order.is_prime():
                p = order
                n = Integer(1)
                if impl is None:
                    impl = 'modn'
                name = ('x',)  # Ignore name
                # Every polynomial of degree 1 is irreducible
                check_irreducible = False
            # This check should be replaced by order.is_prime_power()
            # if Trac #16878 is fixed.
            elif sage.rings.arith.is_prime_power(order):
                if not names is None: name = names
                name = normalize_names(1,name)

                p, n = order.factor()[0]

                # The following is a temporary solution that allows us
                # to construct compatible systems of finite fields
                # until algebraic closures of finite fields are
                # implemented in Sage.  It requires the user to
                # specify two parameters:
                #
                # - `conway` -- boolean; if True, this field is
                #   constructed to fit in a compatible system using
                #   a Conway polynomial.
                # - `prefix` -- a string used to generate names for
                #   automatically constructed finite fields
                #
                # See the docstring of FiniteFieldFactory for examples.
                #
                # Once algebraic closures of finite fields are
                # implemented, this syntax should be superseded by
                # something like the following:
                #
                #     sage: Fpbar = GF(5).algebraic_closure('z')
                #     sage: F, e = Fpbar.subfield(3)  # e is the embedding into Fpbar
                #     sage: F
                #     Finite field in z3 of size 5^3
                #
                # This temporary solution only uses actual Conway
                # polynomials (no pseudo-Conway polynomials), since
                # pseudo-Conway polynomials are not unique, and until
                # we have algebraic closures of finite fields, there
                # is no good place to store a specific choice of
                # pseudo-Conway polynomials.
                if name is None:
                    if not ('conway' in kwds and kwds['conway']):
                        raise ValueError("parameter 'conway' is required if no name given")
                    if 'prefix' not in kwds:
                        raise ValueError("parameter 'prefix' is required if no name given")
                    name = kwds['prefix'] + str(n)

                if 'conway' in kwds and kwds['conway']:
                    from conway_polynomials import conway_polynomial
                    if 'prefix' not in kwds:
                        raise ValueError("a prefix must be specified if conway=True")
                    if modulus is not None:
                        raise ValueError("no modulus may be specified if conway=True")
                    # The following raises a RuntimeError if no polynomial is found.
                    modulus = conway_polynomial(p, n)

                if impl is None:
                    if order < zech_log_bound:
                        impl = 'givaro'
                    elif p == 2:
                        impl = 'ntl'
                    else:
                        impl = 'pari_ffelt'
            else:
                raise ValueError("the order of a finite field must be a prime power")

            # Determine modulus.
            # For the 'modn' implementation, we use the following
            # optimization which we also need to avoid an infinite loop:
            # a modulus of None is a shorthand for x-1.
            if modulus is not None or impl != 'modn':
                R = PolynomialRing(FiniteField(p), 'x')
                if modulus is None:
                    modulus = R.irreducible_element(n)
                if isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus == "default":
                        from sage.misc.superseded import deprecation
                        deprecation(16983, "the modulus 'default' is deprecated, use modulus=None instead (which is the default)")
                        modulus = None
                    modulus = R.irreducible_element(n, algorithm=modulus)
                else:
                    if sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
                        modulus = modulus.change_variable_name('x')
                    modulus = R(modulus).monic()

                    if modulus.degree() != n:
                        raise ValueError("the degree of the modulus does not equal the degree of the field")
                    if check_irreducible and not modulus.is_irreducible():
                        raise ValueError("finite field modulus must be irreducible but it is not")
                # If modulus is x - 1 for impl="modn", set it to None
                if impl == 'modn' and modulus[0] == -1:
                    modulus = None

            return (order, name, modulus, impl, str(kwds), p, n, proof), kwds