Path: blob/master/sage/rings/finite_rings/constructor.py
4069 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_ext_pari.FiniteField_ext_pari_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 2*a802 a + 1813 a + 2824 2835 a846 2*a + 2857 2*a + 1868 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_ext_pari.FiniteField_ext_pari_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.gap170import sage.databases.conway171172from sage.structure.factory import UniqueFactory173174class FiniteFieldFactory(UniqueFactory):175"""176Return the globally unique finite field of given order with177generator labeled by the given name and possibly with given178modulus.179180INPUT:181182183- ``order`` - int184185- ``name`` - string; must be specified if not a prime186field187188- ``modulus`` - (optional) either a defining polynomial for the189field, i.e., generator of the field will be a root of this190polynomial; or a string:191192- 'conway': force the use of a Conway polynomial, will193raise a RuntimeError if none is found in the database;194- 'random': use a random irreducible polynomial;195- 'default': a Conway polynomial is used if found. Otherwise196a sparse polynomial is used for binary fields and a197random polynomial is used for other characteristics.198199Other options might be available depending on the200implementation.201202- ``elem_cache`` - cache all elements to avoid203creation time (default: order < 500)204205- ``check_irreducible`` - verify that the polynomial206modulus is irreducible207208- ``proof`` -- bool (default: True); if True use provable209primality test; otherwise only use pseudoprimality test.210211- ``args`` - additional parameters passed to finite212field implementations213214- ``kwds`` - additional keyword parameters passed to215finite field implementations216217218ALIAS: You can also use GF instead of FiniteField - they are219identical.220221EXAMPLES::222223sage: k.<a> = FiniteField(9); k224Finite Field in a of size 3^2225sage: parent(a)226Finite Field in a of size 3^2227sage: charpoly(a, 'y')228y^2 + 2*y + 2229230We illustrate the proof flag. The following example would hang231for a very long time if we didn't use proof=False. (NOTE: Magma232only supports proof=False for making finite fields, so falsely233appears to be faster than Sage -- see Trac 10975.)::234235sage: k = FiniteField(10^1000 + 453, proof=False)236sage: k = FiniteField((10^1000 + 453)^2, 'a', proof=False) # long time -- about 5 seconds237238::239240sage: F.<x> = GF(5)[]241sage: K.<a> = GF(5**5, name='a', modulus=x^5 - x +1 )242sage: f = K.modulus(); f243x^5 + 4*x + 1244sage: type(f)245<type 'sage.rings.polynomial.polynomial_zmod_flint.Polynomial_zmod_flint'>246247The modulus must be irreducible::248249sage: K.<a> = GF(5**5, name='a', modulus=x^5 - x )250Traceback (most recent call last):251...252ValueError: finite field modulus must be irreducible but it is not.253254You can't accidentally fool the constructor into thinking the modulus255is irreducible when it isn't mod p, since it actually tests256irreducibility modulo p. Also, the modulus has to be of the right degree.257258::259260sage: F.<x> = QQ[]261sage: factor(x^5 + 2)262x^5 + 2263sage: K.<a> = GF(5**5, name='a', modulus=x^5 + 2 )264Traceback (most recent call last):265...266ValueError: finite field modulus must be irreducible but it is not.267sage: K.<a> = GF(5**5, name='a', modulus=x^3 + 3*x + 3)268Traceback (most recent call last):269...270ValueError: The degree of the modulus does not correspond to the271cardinality of the field.272273If you wish to live dangerously, you can tell the constructor not274to test irreducibility using check_irreducible=False, but this can275easily lead to crashes and hangs - so do not do it unless you know276that the modulus really is irreducible and has the correct degree!277278::279280sage: F.<x> = GF(5)[]281sage: K.<a> = GF(5**2, name='a', modulus=x^2 + 2, check_irreducible=False)282283::284285sage: L = GF(3**2, name='a', modulus=QQ[x](x - 1), check_irreducible=False)286sage: L.list() # random287[0, a, 1, 2, 1, 2, 1, 2, 1]288289The order of a finite field must be a prime power::290291sage: GF(1)292Traceback (most recent call last):293...294ValueError: the order of a finite field must be > 1.295sage: GF(100)296Traceback (most recent call last):297...298ValueError: the order of a finite field must be a prime power.299300Finite fields with explicit random modulus are not cached::301302sage: k.<a> = GF(5**10, modulus='random')303sage: n.<a> = GF(5**10, modulus='random')304sage: n is k305False306sage: GF(5**10, 'a') is GF(5**10, 'a')307True308309We check that various ways of creating the same finite field yield310the same object, which is cached.311312::313314sage: K = GF(7, 'a')315sage: L = GF(7, 'b')316sage: K is L317True318sage: K = GF(4,'a'); K.modulus()319x^2 + x + 1320sage: L = GF(4,'a', K.modulus())321sage: K is L322True323sage: M = GF(4,'a', K.modulus().change_variable_name('y'))324sage: K is M325True326327You may print finite field elements as integers. This328currently only works if the order of field is `<2^{16}`,329though.330331::332333sage: k.<a> = GF(2^8, repr='int')334sage: a3352336337"""338def create_key_and_extra_args(self, order, name=None, modulus=None, names=None,339impl=None, proof=None, **kwds):340"""341EXAMPLES::342343sage: GF.create_key_and_extra_args(9, 'a')344((9, ('a',), 'conway', None, '{}', 3, 2, True), {})345sage: GF.create_key_and_extra_args(9, 'a', foo='value')346((9, ('a',), 'conway', None, "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})347"""348from sage.structure.proof.all import WithProof, arithmetic349if proof is None: proof = arithmetic()350with WithProof('arithmetic', proof):351order = int(order)352if order <= 1:353raise ValueError("the order of a finite field must be > 1.")354355if arith.is_prime(order):356name = None357modulus = None358p = integer.Integer(order)359n = integer.Integer(1)360elif arith.is_prime_power(order):361if not names is None: name = names362name = normalize_names(1,name)363364p, n = arith.factor(order)[0]365366if modulus is None or modulus == "default":367if exists_conway_polynomial(p, n):368modulus = "conway"369else:370if p == 2:371modulus = "minimal_weight"372else:373modulus = "random"374elif modulus == "random":375modulus += str(random.randint(0, 1<<128))376377if isinstance(modulus, (list, tuple)):378modulus = FiniteField(p)['x'](modulus)379# some classes use 'random' as the modulus to380# generate a random modulus, but we don't want381# to cache it382elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):383modulus = modulus.change_variable_name('x')384elif not isinstance(modulus, str):385raise ValueError("Modulus parameter not understood.")386else: # Neither a prime, nor a prime power387raise ValueError("the order of a finite field must be a prime power.")388389return (order, name, modulus, impl, str(kwds), p, n, proof), kwds390391def create_object(self, version, key, check_irreducible=True, elem_cache=None,392names=None, **kwds):393"""394EXAMPLES::395396sage: K = GF(19) # indirect doctest397sage: TestSuite(K).run()398"""399# IMPORTANT! If you add a new class to the list of classes400# that get cached by this factor object, then you *must* add401# the following method to that class in order to fully support402# pickling:403#404# def __reduce__(self): # and include good doctests, please!405# return self._factory_data[0].reduce_data(self)406#407# This is not in the base class for finite fields, since some finite408# fields need not be created using this factory object, e.g., residue409# class fields.410411if len(key) == 5:412# for backward compatibility of pickles (see trac 10975).413order, name, modulus, impl, _ = key414p, n = arith.factor(order)[0]415proof = True416else:417order, name, modulus, impl, _, p, n, proof = key418419if isinstance(modulus, str) and modulus.startswith("random"):420modulus = "random"421422if elem_cache is None:423elem_cache = order < 500424425if n == 1 and (impl is None or impl == 'modn'):426from finite_field_prime_modn import FiniteField_prime_modn427# Using a check option here is probably a worthwhile428# compromise since this constructor is simple and used a429# huge amount.430K = FiniteField_prime_modn(order, check=False, **kwds)431else:432# We have to do this with block so that the finite field433# constructors below will use the proof flag that was434# passed in when checking for primality, factoring, etc.435# Otherwise, we would have to complicate all of their436# constructors with check options (like above).437from sage.structure.proof.all import WithProof438with WithProof('arithmetic', proof):439if check_irreducible and polynomial_element.is_Polynomial(modulus):440if modulus.parent().base_ring().characteristic() == 0:441modulus = modulus.change_ring(FiniteField(p))442if not modulus.is_irreducible():443raise ValueError("finite field modulus must be irreducible but it is not.")444if modulus.degree() != n:445raise ValueError("The degree of the modulus does not correspond to the cardinality of the field.")446if name is None:447raise TypeError("you must specify the generator name.")448if order < zech_log_bound:449# DO *NOT* use for prime subfield, since that would lead to450# a circular reference in the call to ParentWithGens in the451# __init__ method.452K = FiniteField_givaro(order, name, modulus, cache=elem_cache,**kwds)453else:454if order % 2 == 0 and (impl is None or impl == 'ntl'):455from finite_field_ntl_gf2e import FiniteField_ntl_gf2e456K = FiniteField_ntl_gf2e(order, name, modulus, **kwds)457else:458from finite_field_ext_pari import FiniteField_ext_pari459K = FiniteField_ext_pari(order, name, modulus, **kwds)460461return K462463def other_keys(self, key, K):464"""465EXAMPLES::466467sage: key, extra = GF.create_key_and_extra_args(9, 'a'); key468(9, ('a',), 'conway', None, '{}', 3, 2, True)469sage: K = GF.create_object(0, key); K470Finite Field in a of size 3^2471sage: GF.other_keys(key, K)472[(9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True),473(9, ('a',), x^2 + 2*x + 2, 'givaro', '{}', 3, 2, True)]474"""475if len(key) == 5: # backward compat476order, name, modulus, impl, _ = key477p, n = arith.factor(order)[0]478proof = True479else:480order, name, modulus, impl, _, p, n, proof = key481482from sage.structure.proof.all import WithProof483with WithProof('arithmetic', proof):484if K.degree() > 1:485modulus = K.modulus().change_variable_name('x')486new_keys = [(order, name, modulus, impl, _, p, n, proof)]487from finite_field_prime_modn import FiniteField_prime_modn488if isinstance(K, FiniteField_prime_modn):489impl = 'modn'490elif isinstance(K, FiniteField_givaro):491impl = 'givaro'492else:493from finite_field_ntl_gf2e import FiniteField_ntl_gf2e494from finite_field_ext_pari import FiniteField_ext_pari495if isinstance(K, FiniteField_ntl_gf2e):496impl = 'ntl'497elif isinstance(K, FiniteField_ext_pari):498impl = 'pari'499new_keys.append( (order, name, modulus, impl, _, p, n, proof) )500return new_keys501502503GF = FiniteField = FiniteFieldFactory("FiniteField")504505506def is_PrimeFiniteField(x):507"""508Returns True if x is a prime finite field.509510EXAMPLES::511512sage: from sage.rings.finite_rings.constructor import is_PrimeFiniteField513sage: is_PrimeFiniteField(QQ)514False515sage: is_PrimeFiniteField(GF(7))516True517sage: is_PrimeFiniteField(GF(7^2,'a'))518False519sage: is_PrimeFiniteField(GF(next_prime(10^90,proof=False)))520True521"""522from finite_field_prime_modn import FiniteField_prime_modn523from sage.rings.finite_rings.finite_field_base import FiniteField as FiniteField_generic524525return isinstance(x, FiniteField_prime_modn) or \526(isinstance(x, FiniteField_generic) and x.degree() == 1)527528##################################################################529530def conway_polynomial(p, n):531r"""532Return the Conway polynomial of degree n over GF(p), which is533loaded from a table.534535If the requested polynomial is not known, this function raises a536RuntimeError exception.537538INPUT:539540541- ``p`` - int542543- ``n`` - int544545546OUTPUT:547548549- ``Polynomial`` - a polynomial over the prime finite550field GF(p).551552553.. note::554555The first time this function is called a table is read from556disk, which takes a fraction of a second. Subsequent calls do557not require reloading the table.558559See also the ``ConwayPolynomials()`` object, which is a560table of Conway polynomials. For example, if561``c=ConwayPolynomials()``, then562``c.primes()`` is a list of all primes for which the563polynomials are known, and for a given prime `p`,564``c.degree(p)`` is a list of all degrees for which the565Conway polynomials are known.566567EXAMPLES::568569sage: conway_polynomial(2,5)570x^5 + x^2 + 1571sage: conway_polynomial(101,5)572x^5 + 2*x + 99573sage: conway_polynomial(97,101)574Traceback (most recent call last):575...576RuntimeError: requested conway polynomial not in database.577"""578(p,n)=(int(p),int(n))579R = FiniteField(p)['x']580try:581return R(sage.databases.conway.ConwayPolynomials()[p][n])582except KeyError:583raise RuntimeError("requested conway polynomial not in database.")584585def exists_conway_polynomial(p, n):586r"""587Return True if the Conway polynomial over `F_p` of degree588`n` is in the database and False otherwise.589590If the Conway polynomial is in the database, to obtain it use the591command ``conway_polynomial(p,n)``.592593EXAMPLES::594595sage: exists_conway_polynomial(2,3)596True597sage: exists_conway_polynomial(2,-1)598False599sage: exists_conway_polynomial(97,200)600False601sage: exists_conway_polynomial(6,6)602False603"""604return sage.databases.conway.ConwayPolynomials().has_polynomial(p,n)605606607zech_log_bound = 2**16608609610