Example #1
0
    def create_key_and_extra_args(self, order, name=None, modulus=None, names=None,
                                  impl=None, proof=None, **kwds):
        """
        EXAMPLES::

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

            if arith.is_prime(order):
                name = None
                modulus = None
                p = integer.Integer(order)
                n = integer.Integer(1)
            elif arith.is_prime_power(order):
                if not names is None: name = names
                name = normalize_names(1,name)

                p, n = arith.factor(order)[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 (kwds.has_key('conway') and kwds['conway']):
                        raise ValueError("parameter 'conway' is required if no name given")
                    if not kwds.has_key('prefix'):
                        raise ValueError("parameter 'prefix' is required if no name given")
                    name = kwds['prefix'] + str(n)

                if kwds.has_key('conway') and kwds['conway']:
                    from conway_polynomials import conway_polynomial
                    if not kwds.has_key('prefix'):
                        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 modulus is None or isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus == "default":    # for backward compatibility
                        modulus = None
                    modulus = GF(p)['x'].irreducible_element(n, algorithm=modulus)
                elif isinstance(modulus, (list, tuple)):
                    modulus = GF(p)['x'](modulus)
                elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
                    modulus = modulus.change_variable_name('x')
                else:
                    raise TypeError("wrong type for modulus parameter")
            else:
                raise ValueError("the order of a finite field must be a prime power.")

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

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

            if arith.is_prime(order):
                name = None
                modulus = None
                p = integer.Integer(order)
                n = integer.Integer(1)
            elif arith.is_prime_power(order):
                if not names is None: name = names
                name = normalize_names(1, name)

                p, n = arith.factor(order)[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 (kwds.has_key('conway') and kwds['conway']):
                        raise ValueError(
                            "parameter 'conway' is required if no name given")
                    if not kwds.has_key('prefix'):
                        raise ValueError(
                            "parameter 'prefix' is required if no name given")
                    name = kwds['prefix'] + str(n)

                if kwds.has_key('conway') and kwds['conway']:
                    from conway_polynomials import conway_polynomial
                    if not kwds.has_key('prefix'):
                        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 modulus is None or isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus == "default":  # for backward compatibility
                        modulus = None
                    modulus = GF(p)['x'].irreducible_element(n,
                                                             algorithm=modulus)
                elif isinstance(modulus, (list, tuple)):
                    modulus = GF(p)['x'](modulus)
                elif sage.rings.polynomial.polynomial_element.is_Polynomial(
                        modulus):
                    modulus = modulus.change_variable_name('x')
                else:
                    raise TypeError("wrong type for modulus parameter")
            else:
                raise ValueError(
                    "the order of a finite field must be a prime power.")

            return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
Example #3
0
    def __init__(self, q, name, modulus=None):
        """
        Create finite field of order `q` with variable printed as name.

        EXAMPLES::

            sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
            sage: k = FiniteField_ext_pari(9, 'a'); k
            Finite Field in a of size 3^2
        """
        if element_ext_pari.dynamic_FiniteField_ext_pariElement is None: element_ext_pari._late_import()
        from constructor import FiniteField as GF
        q = integer.Integer(q)
        if q < 2:
            raise ArithmeticError("q must be a prime power")
        from sage.structure.proof.all import arithmetic
        proof = arithmetic()
        if proof:
            F = q.factor()
        else:
            from sage.rings.arith import is_pseudoprime_small_power
            F = is_pseudoprime_small_power(q, get_data=True)
        if len(F) != 1:
            raise ArithmeticError("q must be a prime power")

        if F[0][1] > 1:
            base_ring = GF(F[0][0])
        else:
            raise ValueError("The size of the finite field must not be prime.")
            #base_ring = self

        FiniteField_generic.__init__(self, base_ring, name, normalize=True)

        self._kwargs = {}
        self.__char = F[0][0]
        self.__pari_one = pari.pari(1).Mod(self.__char)
        self.__degree = integer.Integer(F[0][1])
        self.__order = q
        self.__is_field = True

        if modulus is None or modulus == "default":
            from conway_polynomials import exists_conway_polynomial
            if exists_conway_polynomial(self.__char, self.__degree):
                modulus = "conway"
            else:
                modulus = "random"

        if isinstance(modulus,str):
            if modulus == "conway":
                from conway_polynomials import conway_polynomial
                modulus = conway_polynomial(self.__char, self.__degree)
            elif modulus == "random":
                # The following is fast/deterministic, but has serious problems since
                # it crashes on 64-bit machines, and I can't figure out why:
                #     self.__pari_modulus = pari.pari.finitefield_init(self.__char, self.__degree, self.variable_name())
                # So instead we iterate through random polys until we find an irreducible one.

                R = GF(self.__char)['x']
                while True:
                    modulus = R.random_element(self.__degree)
                    modulus = modulus.monic()
                    if modulus.degree() == self.__degree and modulus.is_irreducible():
                        break
            else:
                raise ValueError("Modulus parameter not understood")

        elif isinstance(modulus, (list, tuple)):
            modulus = GF(self.__char)['x'](modulus)
        elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
            if modulus.parent() is not base_ring:
                modulus = modulus.change_ring(base_ring)
        else:
            raise ValueError("Modulus parameter not understood")

        self.__modulus = modulus
        f = pari.pari(str(modulus))
        self.__pari_modulus = f.subst(modulus.parent().variable_name(), 'a') * self.__pari_one
        self.__gen = element_ext_pari.FiniteField_ext_pariElement(self, pari.pari('a'))

        self._zero_element = self._element_constructor_(0)
        self._one_element = self._element_constructor_(1)
Example #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
Example #5
0
    def __init__(self, q, name, modulus=None):
        """
        Create finite field of order `q` with variable printed as name.

        EXAMPLES::

            sage: k = FiniteField(9, 'a', impl='pari_mod'); k
            Finite Field in a of size 3^2
        """
        from sage.misc.superseded import deprecation
        deprecation(17297, 'The "pari_mod" finite field implementation is deprecated')

        if element_ext_pari.dynamic_FiniteField_ext_pariElement is None: element_ext_pari._late_import()
        from constructor import FiniteField as GF
        q = integer.Integer(q)
        if q < 2:
            raise ArithmeticError("q must be a prime power")

        # note: the following call takes care of the fact that
        # proof.arithmetic() is True or False.
        p, n = q.is_prime_power(get_data=True)
        if n > 1:
            base_ring = GF(p)
        elif n == 0:
            raise ArithmeticError("q must be a prime power")
        else:
            raise ValueError("The size of the finite field must not be prime.")

        FiniteField_generic.__init__(self, base_ring, name, normalize=True)

        self._kwargs = {}
        self.__char = p
        self.__pari_one = pari.pari(1).Mod(self.__char)
        self.__degree = n
        self.__order = q
        self.__is_field = True

        if not sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
            from sage.misc.superseded import deprecation
            deprecation(16930, "constructing a FiniteField_ext_pari without giving a polynomial as modulus is deprecated, use the more general FiniteField constructor instead")

        if modulus is None or modulus == "default":
            from conway_polynomials import exists_conway_polynomial
            if exists_conway_polynomial(self.__char, self.__degree):
                modulus = "conway"
            else:
                modulus = "random"

        if isinstance(modulus,str):
            if modulus == "conway":
                from conway_polynomials import conway_polynomial
                modulus = conway_polynomial(self.__char, self.__degree)
            elif modulus == "random":
                # The following is fast/deterministic, but has serious problems since
                # it crashes on 64-bit machines, and I can't figure out why:
                #     self.__pari_modulus = pari.pari.finitefield_init(self.__char, self.__degree, self.variable_name())
                # So instead we iterate through random polys until we find an irreducible one.

                R = GF(self.__char)['x']
                while True:
                    modulus = R.random_element(self.__degree)
                    modulus = modulus.monic()
                    if modulus.degree() == self.__degree and modulus.is_irreducible():
                        break
            else:
                raise ValueError("Modulus parameter not understood")

        elif isinstance(modulus, (list, tuple)):
            modulus = GF(self.__char)['x'](modulus)
        elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
            if modulus.base_ring() is not base_ring:
                modulus = modulus.change_ring(base_ring)
        else:
            raise ValueError("Modulus parameter not understood")

        self._modulus = modulus
        f = pari.pari(str(modulus))
        self.__pari_modulus = f.subst(modulus.parent().variable_name(), 'a') * self.__pari_one
        self.__gen = element_ext_pari.FiniteField_ext_pariElement(self, pari.pari('a'))

        self._zero_element = self._element_constructor_(0)
        self._one_element = self._element_constructor_(1)
Example #6
0
    def __init__(self, q, name, modulus=None):
        """
        Create finite field of order `q` with variable printed as name.

        EXAMPLES::

            sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
            sage: k = FiniteField_ext_pari(9, 'a'); k
            Finite Field in a of size 3^2
        """
        if element_ext_pari.dynamic_FiniteField_ext_pariElement is None: element_ext_pari._late_import()
        from constructor import FiniteField as GF
        q = integer.Integer(q)
        if q < 2:
            raise ArithmeticError, "q must be a prime power"
        from sage.structure.proof.all import arithmetic
        proof = arithmetic()
        if proof:
            F = q.factor()
        else:
            from sage.rings.arith import is_pseudoprime_small_power
            F = is_pseudoprime_small_power(q, get_data=True)
        if len(F) != 1:
            raise ArithmeticError, "q must be a prime power"

        if F[0][1] > 1:
            base_ring = GF(F[0][0])
        else:
            raise ValueError, "The size of the finite field must not be prime."
            #base_ring = self

        FiniteField_generic.__init__(self, base_ring, name, normalize=True)

        self._kwargs = {}
        self.__char = F[0][0]
        self.__pari_one = pari.pari(1).Mod(self.__char)
        self.__degree = integer.Integer(F[0][1])
        self.__order = q
        self.__is_field = True

        if modulus is None or modulus == "default":
            from conway_polynomials import exists_conway_polynomial
            if exists_conway_polynomial(self.__char, self.__degree):
                modulus = "conway"
            else:
                modulus = "random"

        if isinstance(modulus,str):
            if modulus == "conway":
                from conway_polynomials import conway_polynomial
                modulus = conway_polynomial(self.__char, self.__degree)
            elif modulus == "random":
                # The following is fast/deterministic, but has serious problems since
                # it crashes on 64-bit machines, and I can't figure out why:
                #     self.__pari_modulus = pari.pari.finitefield_init(self.__char, self.__degree, self.variable_name())
                # So instead we iterate through random polys until we find an irreducible one.

                R = GF(self.__char)['x']
                while True:
                    modulus = R.random_element(self.__degree)
                    modulus = modulus.monic()
                    if modulus.degree() == self.__degree and modulus.is_irreducible():
                        break
            else:
                raise ValueError("Modulus parameter not understood")

        elif isinstance(modulus, (list, tuple)):
            modulus = GF(self.__char)['x'](modulus)
        elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
            if modulus.parent() is not base_ring:
                modulus = modulus.change_ring(base_ring)
        else:
            raise ValueError("Modulus parameter not understood")

        self.__modulus = modulus
        f = pari.pari(str(modulus))
        self.__pari_modulus = f.subst(modulus.parent().variable_name(), 'a') * self.__pari_one
        self.__gen = element_ext_pari.FiniteField_ext_pariElement(self, pari.pari('a'))

        self._zero_element = self._element_constructor_(0)
        self._one_element = self._element_constructor_(1)
Example #7
0
    def __init__(self, q, name, modulus=None):
        """
        Create finite field of order `q` with variable printed as name.

        EXAMPLES::

            sage: k = FiniteField(9, 'a', impl='pari_mod'); k
            Finite Field in a of size 3^2
        """
        from sage.misc.superseded import deprecation
        deprecation(
            17297, 'The "pari_mod" finite field implementation is deprecated')

        if element_ext_pari.dynamic_FiniteField_ext_pariElement is None:
            element_ext_pari._late_import()
        from finite_field_constructor import FiniteField as GF
        q = integer.Integer(q)
        if q < 2:
            raise ArithmeticError("q must be a prime power")

        # note: the following call takes care of the fact that
        # proof.arithmetic() is True or False.
        p, n = q.is_prime_power(get_data=True)
        if n > 1:
            base_ring = GF(p)
        elif n == 0:
            raise ArithmeticError("q must be a prime power")
        else:
            raise ValueError("The size of the finite field must not be prime.")

        FiniteField_generic.__init__(self, base_ring, name, normalize=True)

        self._kwargs = {}
        self.__char = p
        self.__pari_one = pari.pari(1).Mod(self.__char)
        self.__degree = n
        self.__order = q
        self.__is_field = True

        if not sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
            from sage.misc.superseded import deprecation
            deprecation(
                16930,
                "constructing a FiniteField_ext_pari without giving a polynomial as modulus is deprecated, use the more general FiniteField constructor instead"
            )

        if modulus is None or modulus == "default":
            from conway_polynomials import exists_conway_polynomial
            if exists_conway_polynomial(self.__char, self.__degree):
                modulus = "conway"
            else:
                modulus = "random"

        if isinstance(modulus, str):
            if modulus == "conway":
                from conway_polynomials import conway_polynomial
                modulus = conway_polynomial(self.__char, self.__degree)
            elif modulus == "random":
                # The following is fast/deterministic, but has serious problems since
                # it crashes on 64-bit machines, and I can't figure out why:
                #     self.__pari_modulus = pari.pari.finitefield_init(self.__char, self.__degree, self.variable_name())
                # So instead we iterate through random polys until we find an irreducible one.

                R = GF(self.__char)['x']
                while True:
                    modulus = R.random_element(self.__degree)
                    modulus = modulus.monic()
                    if modulus.degree(
                    ) == self.__degree and modulus.is_irreducible():
                        break
            else:
                raise ValueError("Modulus parameter not understood")

        elif isinstance(modulus, (list, tuple)):
            modulus = GF(self.__char)['x'](modulus)
        elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
            if modulus.base_ring() is not base_ring:
                modulus = modulus.change_ring(base_ring)
        else:
            raise ValueError("Modulus parameter not understood")

        self._modulus = modulus
        f = pari.pari(str(modulus))
        self.__pari_modulus = f.subst(modulus.parent().variable_name(),
                                      'a') * self.__pari_one
        self.__gen = element_ext_pari.FiniteField_ext_pariElement(
            self, pari.pari('a'))

        self._zero_element = self._element_constructor_(0)
        self._one_element = self._element_constructor_(1)
Example #8
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