Path: blob/master/src/sage/rings/finite_rings/constructor.py
8820 views
r"""1Finite Fields23Sage supports arithmetic in finite prime and extension fields.4Several implementation for prime fields are implemented natively in5Sage for several sizes of primes `p`. These implementations6are789- ``sage.rings.finite_rings.integer_mod.IntegerMod_int``,1011- ``sage.rings.finite_rings.integer_mod.IntegerMod_int64``, and1213- ``sage.rings.finite_rings.integer_mod.IntegerMod_gmp``.141516Small extension fields of cardinality `< 2^{16}` are17implemented using tables of Zech logs via the Givaro C++ library18(``sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro``).19While this representation is very fast it is limited to finite20fields of small cardinality. Larger finite extension fields of21order `q >= 2^{16}` are internally represented as22polynomials over smaller finite prime fields. If the23characteristic of such a field is 2 then NTL is used internally to24represent the field25(``sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e``).26In all other case the PARI C library is used27(``sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari``).2829However, this distinction is internal only and the user usually30does not have to worry about it because consistency across all31implementations is aimed for. In all extension field32implementations the user may either specify a minimal polynomial or33leave the choice to Sage.3435For small finite fields the default choice are Conway polynomials.3637The Conway polynomial `C_n` is the lexicographically first38monic irreducible, primitive polynomial of degree `n` over39`GF(p)` with the property that for a root `\alpha`40of `C_n` we have that41`\beta=42\alpha^{(p^n - 1)/(p^m - 1)}` is a root of43`C_m` for all `m` dividing `n`. Sage44contains a database of Conway polynomials which also can be queried45independently of finite field construction.4647While Sage supports basic arithmetic in finite fields some more48advanced features for computing with finite fields are still not49implemented. For instance, Sage does not calculate embeddings of50finite fields yet.5152EXAMPLES::5354sage: k = GF(5); type(k)55<class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>5657::5859sage: k = GF(5^2,'c'); type(k)60<class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>6162::6364sage: k = GF(2^16,'c'); type(k)65<class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>6667::6869sage: k = GF(3^16,'c'); type(k)70<class 'sage.rings.finite_rings.finite_field_pari_ffelt.FiniteField_pari_ffelt_with_category'>7172Finite Fields support iteration, starting with 0.7374::7576sage: k = GF(9, 'a')77sage: for i,x in enumerate(k): print i,x780 0791 a802 a + 1813 2*a + 1824 2835 2*a846 2*a + 2857 a + 2868 187sage: for a in GF(5):88... print a8909019129239349495We output the base rings of several finite fields.9697::9899sage: k = GF(3); type(k)100<class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>101sage: k.base_ring()102Finite Field of size 3103104::105106sage: k = GF(9,'alpha'); type(k)107<class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>108sage: k.base_ring()109Finite Field of size 3110111::112113sage: k = GF(3^40,'b'); type(k)114<class 'sage.rings.finite_rings.finite_field_pari_ffelt.FiniteField_pari_ffelt_with_category'>115sage: k.base_ring()116Finite Field of size 3117118Further examples::119120sage: GF(2).is_field()121True122sage: GF(next_prime(10^20)).is_field()123True124sage: GF(19^20,'a').is_field()125True126sage: GF(8,'a').is_field()127True128129AUTHORS:130131- William Stein: initial version132133- Robert Bradshaw: prime field implementation134135- Martin Albrecht: Givaro and ntl.GF2E implementations136"""137138#*****************************************************************************139# Copyright (C) 2006 William Stein <[email protected]>140#141# Distributed under the terms of the GNU General Public License (GPL)142#143# This code is distributed in the hope that it will be useful,144# but WITHOUT ANY WARRANTY; without even the implied warranty of145# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU146# General Public License for more details.147#148# The full text of the GPL is available at:149#150# http://www.gnu.org/licenses/151#*****************************************************************************152153import random154155from sage.rings.finite_rings.finite_field_base import is_FiniteField156from sage.structure.parent_gens import normalize_names157158import sage.rings.arith as arith159import sage.rings.integer as integer160161import sage.rings.polynomial.polynomial_element as polynomial_element162import sage.rings.polynomial.multi_polynomial_element as multi_polynomial_element163164# We don't late import this because this means trouble with the Givaro library165# On a Macbook Pro OSX 10.5.8, this manifests as a Bus Error on exiting Sage.166# TODO: figure out why167from finite_field_givaro import FiniteField_givaro168169import sage.interfaces.gap170171from sage.structure.factory import UniqueFactory172173class FiniteFieldFactory(UniqueFactory):174"""175Return the globally unique finite field of given order with176generator labeled by the given name and possibly with given177modulus.178179INPUT:180181- ``order`` -- a prime power182183- ``name`` -- string; must be specified unless ``order`` is prime.184185- ``modulus`` -- (optional) either a defining polynomial for the186field, or a string specifying an algorithm to use to generate187such a polynomial. If ``modulus`` is a string, it is passed to188:meth:`~sage.rings.polynomial.irreducible_element()` as the189parameter ``algorithm``; see there for the permissible values of190this parameter.191192- ``elem_cache`` -- cache all elements to avoid creation time193(default: order < 500)194195- ``check_irreducible`` -- verify that the polynomial modulus is196irreducible197198- ``proof`` -- bool (default: ``True``): if ``True``, use provable199primality test; otherwise only use pseudoprimality test.200201- ``args`` -- additional parameters passed to finite field202implementations203204- ``kwds`` -- additional keyword parameters passed to finite field205implementations206207ALIAS: You can also use ``GF`` instead of ``FiniteField`` -- they208are identical.209210EXAMPLES::211212sage: k.<a> = FiniteField(9); k213Finite Field in a of size 3^2214sage: parent(a)215Finite Field in a of size 3^2216sage: charpoly(a, 'y')217y^2 + 2*y + 2218219We illustrate the proof flag. The following example would hang220for a very long time if we didn't use ``proof=False``.221222.. NOTE::223224Magma only supports ``proof=False`` for making finite fields,225so falsely appears to be faster than Sage -- see :trac:10975.226227::228229sage: k = FiniteField(10^1000 + 453, proof=False)230sage: k = FiniteField((10^1000 + 453)^2, 'a', proof=False) # long time -- about 5 seconds231232::233234sage: F.<x> = GF(5)[]235sage: K.<a> = GF(5**5, name='a', modulus=x^5 - x +1 )236sage: f = K.modulus(); f237x^5 + 4*x + 1238sage: type(f)239<type 'sage.rings.polynomial.polynomial_zmod_flint.Polynomial_zmod_flint'>240241The modulus must be irreducible::242243sage: K.<a> = GF(5**5, name='a', modulus=x^5 - x)244Traceback (most recent call last):245...246ValueError: finite field modulus must be irreducible but it is not.247248You can't accidentally fool the constructor into thinking the249modulus is irreducible when it is not, since it actually tests250irreducibility modulo `p`. Also, the modulus has to be of the251right degree::252253sage: F.<x> = QQ[]254sage: factor(x^5 + 2)255x^5 + 2256sage: K.<a> = GF(5**5, name='a', modulus=x^5 + 2)257Traceback (most recent call last):258...259ValueError: finite field modulus must be irreducible but it is not.260sage: K.<a> = GF(5**5, name='a', modulus=x^3 + 3*x + 3)261Traceback (most recent call last):262...263ValueError: The degree of the modulus does not correspond to the264cardinality of the field.265266If you wish to live dangerously, you can tell the constructor not267to test irreducibility using ``check_irreducible=False``, but this268can easily lead to crashes and hangs -- so do not do it unless you269know that the modulus really is irreducible and has the correct270degree!271272::273274sage: F.<x> = GF(5)[]275sage: K.<a> = GF(5**2, name='a', modulus=x^2 + 2, check_irreducible=False)276277sage: L = GF(3**2, name='a', modulus=QQ[x](x - 1), check_irreducible=False)278sage: L.list() # random279[0, a, 1, 2, 1, 2, 1, 2, 1]280281The order of a finite field must be a prime power::282283sage: GF(1)284Traceback (most recent call last):285...286ValueError: the order of a finite field must be > 1.287sage: GF(100)288Traceback (most recent call last):289...290ValueError: the order of a finite field must be a prime power.291292Finite fields with explicit random modulus are not cached::293294sage: k.<a> = GF(5**10, modulus='random')295sage: n.<a> = GF(5**10, modulus='random')296sage: n is k297False298sage: GF(5**10, 'a') is GF(5**10, 'a')299True300301We check that various ways of creating the same finite field yield302the same object, which is cached::303304sage: K = GF(7, 'a')305sage: L = GF(7, 'b')306sage: K is L307True308sage: K = GF(4,'a'); K.modulus()309x^2 + x + 1310sage: L = GF(4,'a', K.modulus())311sage: K is L312True313sage: M = GF(4,'a', K.modulus().change_variable_name('y'))314sage: K is M315True316317You may print finite field elements as integers. This currently318only works if the order of field is `<2^{16}`, though::319320sage: k.<a> = GF(2^8, repr='int')321sage: a3222323324The following demonstrate coercions for finite fields using Conway325polynomials::326327sage: k = GF(5^2, conway=True, prefix='z'); a = k.gen()328sage: l = GF(5^5, conway=True, prefix='z'); b = l.gen()329sage: a + b3303*z10^5 + z10^4 + z10^2 + 3*z10 + 1331332Note that embeddings are compatible in lattices of such finite333fields::334335sage: m = GF(5^3, conway=True, prefix='z'); c = m.gen()336sage: (a+b)+c == a+(b+c)337True338sage: (a*b)*c == a*(b*c)339True340sage: from sage.categories.pushout import pushout341sage: n = pushout(k, l)342sage: o = pushout(l, m)343sage: q = pushout(n, o)344sage: q(o(b)) == q(n(b))345True346347Another check that embeddings are defined properly::348349sage: k = GF(3**10, conway=True, prefix='z')350sage: l = GF(3**20, conway=True, prefix='z')351sage: l(k.gen()**10) == l(k.gen())**10352True353"""354def create_key_and_extra_args(self, order, name=None, modulus=None, names=None,355impl=None, proof=None, **kwds):356"""357EXAMPLES::358359sage: GF.create_key_and_extra_args(9, 'a')360((9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True), {})361sage: GF.create_key_and_extra_args(9, 'a', foo='value')362((9, ('a',), x^2 + 2*x + 2, None, "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})363"""364from sage.structure.proof.all import WithProof, arithmetic365if proof is None: proof = arithmetic()366with WithProof('arithmetic', proof):367order = int(order)368if order <= 1:369raise ValueError("the order of a finite field must be > 1.")370371if arith.is_prime(order):372name = None373modulus = None374p = integer.Integer(order)375n = integer.Integer(1)376elif arith.is_prime_power(order):377if not names is None: name = names378name = normalize_names(1,name)379380p, n = arith.factor(order)[0]381382# The following is a temporary solution that allows us383# to construct compatible systems of finite fields384# until algebraic closures of finite fields are385# implemented in Sage. It requires the user to386# specify two parameters:387#388# - `conway` -- boolean; if True, this field is389# constructed to fit in a compatible system using390# a Conway polynomial.391# - `prefix` -- a string used to generate names for392# automatically constructed finite fields393#394# See the docstring of FiniteFieldFactory for examples.395#396# Once algebraic closures of finite fields are397# implemented, this syntax should be superseded by398# something like the following:399#400# sage: Fpbar = GF(5).algebraic_closure('z')401# sage: F, e = Fpbar.subfield(3) # e is the embedding into Fpbar402# sage: F403# Finite field in z3 of size 5^3404#405# This temporary solution only uses actual Conway406# polynomials (no pseudo-Conway polynomials), since407# pseudo-Conway polynomials are not unique, and until408# we have algebraic closures of finite fields, there409# is no good place to store a specific choice of410# pseudo-Conway polynomials.411if name is None:412if not (kwds.has_key('conway') and kwds['conway']):413raise ValueError("parameter 'conway' is required if no name given")414if not kwds.has_key('prefix'):415raise ValueError("parameter 'prefix' is required if no name given")416name = kwds['prefix'] + str(n)417418if kwds.has_key('conway') and kwds['conway']:419from conway_polynomials import conway_polynomial420if not kwds.has_key('prefix'):421raise ValueError("a prefix must be specified if conway=True")422if modulus is not None:423raise ValueError("no modulus may be specified if conway=True")424# The following raises a RuntimeError if no polynomial is found.425modulus = conway_polynomial(p, n)426427if modulus is None or isinstance(modulus, str):428# A string specifies an algorithm to find a suitable modulus.429if modulus == "default": # for backward compatibility430modulus = None431modulus = GF(p)['x'].irreducible_element(n, algorithm=modulus)432elif isinstance(modulus, (list, tuple)):433modulus = GF(p)['x'](modulus)434elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):435modulus = modulus.change_variable_name('x')436else:437raise TypeError("wrong type for modulus parameter")438else:439raise ValueError("the order of a finite field must be a prime power.")440441return (order, name, modulus, impl, str(kwds), p, n, proof), kwds442443def create_object(self, version, key, check_irreducible=True, elem_cache=None,444names=None, **kwds):445"""446EXAMPLES::447448sage: K = GF(19) # indirect doctest449sage: TestSuite(K).run()450"""451# IMPORTANT! If you add a new class to the list of classes452# that get cached by this factor object, then you *must* add453# the following method to that class in order to fully support454# pickling:455#456# def __reduce__(self): # and include good doctests, please!457# return self._factory_data[0].reduce_data(self)458#459# This is not in the base class for finite fields, since some finite460# fields need not be created using this factory object, e.g., residue461# class fields.462463if len(key) == 5:464# for backward compatibility of pickles (see trac 10975).465order, name, modulus, impl, _ = key466p, n = arith.factor(order)[0]467proof = True468else:469order, name, modulus, impl, _, p, n, proof = key470471if elem_cache is None:472elem_cache = order < 500473474if n == 1 and (impl is None or impl == 'modn'):475from finite_field_prime_modn import FiniteField_prime_modn476# Using a check option here is probably a worthwhile477# compromise since this constructor is simple and used a478# huge amount.479K = FiniteField_prime_modn(order, check=False)480else:481# We have to do this with block so that the finite field482# constructors below will use the proof flag that was483# passed in when checking for primality, factoring, etc.484# Otherwise, we would have to complicate all of their485# constructors with check options (like above).486from sage.structure.proof.all import WithProof487with WithProof('arithmetic', proof):488if check_irreducible and polynomial_element.is_Polynomial(modulus):489if modulus.parent().base_ring().characteristic() == 0:490modulus = modulus.change_ring(FiniteField(p))491if not modulus.is_irreducible():492raise ValueError("finite field modulus must be irreducible but it is not.")493if modulus.degree() != n:494raise ValueError("The degree of the modulus does not correspond to the cardinality of the field.")495if name is None:496raise TypeError("you must specify the generator name.")497if impl is None:498if order < zech_log_bound:499# DO *NOT* use for prime subfield, since that would lead to500# a circular reference in the call to ParentWithGens in the501# __init__ method.502impl = 'givaro'503elif order % 2 == 0:504impl = 'ntl'505else:506impl = 'pari_ffelt'507if impl == 'givaro':508if kwds.has_key('repr'):509repr = kwds['repr']510else:511repr = 'poly'512K = FiniteField_givaro(order, name, modulus, repr=repr, cache=elem_cache)513elif impl == 'ntl':514from finite_field_ntl_gf2e import FiniteField_ntl_gf2e515K = FiniteField_ntl_gf2e(order, name, modulus)516elif impl == 'pari_ffelt':517from finite_field_pari_ffelt import FiniteField_pari_ffelt518K = FiniteField_pari_ffelt(p, modulus, name)519elif (impl == 'pari_mod'520or impl == 'pari'): # for unpickling old pickles521from finite_field_ext_pari import FiniteField_ext_pari522K = FiniteField_ext_pari(order, name, modulus)523else:524raise ValueError("no such finite field implementation: %s" % impl)525526# Temporary; see create_key_and_extra_args() above.527if kwds.has_key('prefix'):528K._prefix = kwds['prefix']529530return K531532def other_keys(self, key, K):533"""534EXAMPLES::535536sage: key, extra = GF.create_key_and_extra_args(9, 'a'); key537(9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True)538sage: K = GF.create_object(0, key); K539Finite Field in a of size 3^2540sage: GF.other_keys(key, K)541[(9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True),542(9, ('a',), x^2 + 2*x + 2, 'givaro', '{}', 3, 2, True)]543"""544if len(key) == 5: # backward compat545order, name, modulus, impl, _ = key546p, n = arith.factor(order)[0]547proof = True548else:549order, name, modulus, impl, _, p, n, proof = key550551from sage.structure.proof.all import WithProof552with WithProof('arithmetic', proof):553if K.degree() > 1:554modulus = K.modulus().change_variable_name('x')555new_keys = [(order, name, modulus, impl, _, p, n, proof)]556from finite_field_prime_modn import FiniteField_prime_modn557if isinstance(K, FiniteField_prime_modn):558impl = 'modn'559elif isinstance(K, FiniteField_givaro):560impl = 'givaro'561else:562from finite_field_ntl_gf2e import FiniteField_ntl_gf2e563from finite_field_ext_pari import FiniteField_ext_pari564from finite_field_pari_ffelt import FiniteField_pari_ffelt565if isinstance(K, FiniteField_ntl_gf2e):566impl = 'ntl'567elif isinstance(K, FiniteField_ext_pari):568impl = 'pari_mod'569elif isinstance(K, FiniteField_pari_ffelt):570impl = 'pari_ffelt'571new_keys.append( (order, name, modulus, impl, _, p, n, proof) )572return new_keys573574575GF = FiniteField = FiniteFieldFactory("FiniteField")576577578def is_PrimeFiniteField(x):579"""580Returns True if x is a prime finite field.581582EXAMPLES::583584sage: from sage.rings.finite_rings.constructor import is_PrimeFiniteField585sage: is_PrimeFiniteField(QQ)586False587sage: is_PrimeFiniteField(GF(7))588True589sage: is_PrimeFiniteField(GF(7^2,'a'))590False591sage: is_PrimeFiniteField(GF(next_prime(10^90,proof=False)))592True593"""594from finite_field_prime_modn import FiniteField_prime_modn595from sage.rings.finite_rings.finite_field_base import FiniteField as FiniteField_generic596597return isinstance(x, FiniteField_prime_modn) or \598(isinstance(x, FiniteField_generic) and x.degree() == 1)599600zech_log_bound = 2**16601602603