# Ticket #14990: trac_14990-algebraic_closure_finite_field.patch

File trac_14990-algebraic_closure_finite_field.patch, 43.5 KB (added by pbruin, 7 years ago)

update (doctest coverage)

• ## doc/en/reference/finite_rings/index.rst

# HG changeset patch
# User Peter Bruin <P.Bruin@warwick.ac.uk>
# Date 1376472492 -7200
# Node ID 7576e85707a44d974e5abe4827abedc97142a454
# Parent  33a4ab61f20f40e2d3ba5f075ab97a4ac368b6b7
Trac 14990: implement algebraic closures of finite fields

diff --git a/doc/en/reference/finite_rings/index.rst b/doc/en/reference/finite_rings/index.rst
 a sage/rings/finite_rings/finite_field_pari_ffelt sage/rings/finite_rings/finite_field_prime_modn sage/rings/finite_rings/homset sage/rings/algebraic_closure_finite_field .. include:: ../footer.txt
• ## sage/matrix/matrix2.pyx

diff --git a/sage/matrix/matrix2.pyx b/sage/matrix/matrix2.pyx
 a sage: A._eigenspace_format('galois') == 'galois' True The algebraic closure of the rationals, the field of algebraic numbers, (aka QQbar) is implemented, while in general the algebraic closure of a finite field is not implemented.  :: The algebraic closure of the rationals (the field QQbar of algebraic numbers) is implemented, as are algebraic closures of finite fields:: sage: A = matrix(QQ, 2, range(4)) sage: A._eigenspace_format(None) == 'all' True sage: B = matrix(GF(13), 2, range(4)) sage: B._eigenspace_format(None) == 'galois' True sage: B._eigenspace_format(None) 'all' Subrings are promoted to fraction fields and then checked for the existence of algebraic closures.  :: msg = "format keyword must be None, 'all' or 'galois', not {0}" raise ValueError(msg.format(format)) # For subrings of implemented algebraically closed fields we #   default to all eigenspaces in the absence of a format keyword # Add newly implemented algebraically closed fields to list below #   and implement the determintion of the actual eigenvalues #   in the eigenspace_left() routine # In the absence of a format keyword, we default to 'all' for # subrings of fields of which an algebraic closure is implemented. if format is None: R = self.base_ring() from sage.rings.qqbar import QQbar try: if R.fraction_field().algebraic_closure() in [QQbar]: return 'all' F = self.base_ring().fraction_field() if F.is_finite(): _ = F.algebraic_closure('z') else: return 'galois' _ = F.algebraic_closure() return 'all' except (NotImplementedError, AttributeError): return 'galois' else: ValueError: matrix is not positive definite, so cannot compute Cholesky decomposition Even in light of the above, you can sometimes get lucky and arrive at a situation where a particular matrix has a Cholesky decomposition when the general characteristics of the matrix suggest this routine would fail. In this example, the indefinite factorization produces a diagonal matrix whose elements from the finite field convert naturally to positive integers and are also perfect squares.  :: In certain cases, the algorithm can find an analogue of the Cholesky decomposition over finite fields:: sage: F. = FiniteField(5^3) sage: A = matrix(F, [[         4,       2*a^2 + 3,         4*a + 1], sage: L*L.transpose() == A True sage: F = FiniteField(7) sage: A = matrix(F, [[4, 0], [0, 3]]) sage: A.cholesky() [       2        0] [       0 2*z2 + 6] TESTS: This verifies that :trac:11274 is resolved.  :: sqrt = F(x.sqrt()) except (TypeError, ValueError): try: F = F.algebraic_closure() if F.is_finite(): F = F.algebraic_closure('z') else: F = F.algebraic_closure() except (NotImplementedError, AttributeError): msg = "base field needs an algebraic closure with square roots, not {0}" raise TypeError(msg.format(F)) # try again sqrt = F(x.sqrt()) sqrt = F(x).sqrt() splits.append(sqrt) # move square root of the diagonal matrix # into the lower triangular matrix
• ## new file sage/rings/algebraic_closure_finite_field.py

diff --git a/sage/rings/algebraic_closure_finite_field.py b/sage/rings/algebraic_closure_finite_field.py
new file mode 100644
 - r""" Algebraic closures of finite fields Let \Bold{F} be a finite field, and let \overline{\Bold{F}} be an algebraic closure of \Bold{F}; this is unique up to (non-canonical) isomorphism.  For every n\ge 1, there is a unique subfield \Bold{F}_n of \overline{\Bold{F}} such that \Bold{F}\subset\Bold{F}_n and '[\Bold{F}_n:\Bold{F}]=1. In Sage, algebraic closures of finite fields are implemented using compatible systems of finite fields.  The resulting Sage object keeps track of a finite lattice of the subfields \Bold{F}_n and the embeddings between them.  This lattice is extended as necessary. The Sage class corresponding to \overline{\Bold{F}} can be constructed from the finite field \Bold{F} by using the :meth:~sage.rings.finite_rings.finite_field_base.FiniteField.algebraic_closure method.  This invokes the AlgebraicClosureFiniteField factory object to get unique representation. The Sage class for elements of \overline{\Bold{F}} is :class:AlgebraicClosureFiniteFieldElement.  Such an element is represented as an element of one of the \Bold{F}_n.  This means that each element x\in\Bold{F} has infinitely many different representations, one for each n such that x is in \Bold{F}_n. .. NOTE:: Only prime finite fields are currently accepted as base fields for algebraic closures.  To obtain an algebraic closure of a non-prime finite field \Bold{F}, take an algebraic closure of the prime field of \Bold{F} and embed \Bold{F} into this. Algebraic closures of finite fields are currently implemented using (pseudo-)Conway polynomials; see :class:AlgebraicClosureFiniteField_pseudo_conway and the module :mod:~sage.rings.finite_rings.conway_polynomials.  Other implementations may be added by creating appropriate subclasses of :class:AlgebraicClosureFiniteField_generic. TEST:: sage: F = GF(5).algebraic_closure('z') sage: TestSuite(F).run() AUTHORS: - Peter Bruin (August 2013): initial version """ from sage.rings.finite_rings.element_base import is_FiniteFieldElement from sage.rings.finite_rings.finite_field_base import is_FiniteField from sage.rings.ring import Field from sage.structure.element import FieldElement from sage.structure.factory import UniqueFactory class AlgebraicClosureFiniteFieldElement(FieldElement): """ Element of an algebraic closure of a finite field. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: F.gen(2) z2 sage: type(F.gen(2)) """ def __init__(self, parent, value): """ TEST:: sage: F = GF(3).algebraic_closure('z') sage: TestSuite(F.gen(2)).run() """ if is_FiniteFieldElement(value): n = value.parent().degree() else: from sage.rings.integer import Integer n = Integer(1) self._value = parent._subfield(n).coerce(value) self._level = n FieldElement.__init__(self, parent) def __reduce__(self): """ Used for pickling. TESTS:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField sage: F = AlgebraicClosureFiniteField(GF(2), 'z') sage: loads(dumps(F.gen(5))) == F.gen(5) True """ return unpickle_AlgebraicClosureFiniteFieldElement, (self.parent(), self._level, self._repr_()) def _repr_(self): """ Return a string representation of self. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: F._repr_() 'Algebraic closure of Finite Field of size 3' """ return self._value._repr_() def __cmp__(self, right): """ Compare self with right. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: F.gen(2) == F.gen(3) False """ x, y = self.parent()._coerce_2(self, right) return cmp(x, y) def _add_(self, right): """ Return self + right. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: F.gen(2) + F.gen(3) z6^5 + 2*z6^4 + 2*z6^3 + z6^2 + 2*z6 + 1 """ F = self.parent() x, y = F._coerce_2(self, right) return self.__class__(F, x + y) def _sub_(self, right): """ Return self - right. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: F.gen(2) - F.gen(3) z6^4 + 2*z6^3 + z6^2 + 2*z6 """ F = self.parent() x, y = F._coerce_2(self, right) return self.__class__(F, x - y) def _mul_(self, right): """ Return self * right. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: F.gen(2) * F.gen(3) z6^5 + 2*z6^4 + z6^2 + 2 """ F = self.parent() x, y = F._coerce_2(self, right) return self.__class__(F, x * y) def _div_(self, right): """ Return self / right. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: F.gen(2) / F.gen(3) z6^5 + 2*z6^4 + z6^3 + 1 """ F = self.parent() x, y = F._coerce_2(self, right) return self.__class__(F, x / y) def _change_level(self, n): """ Return a representation of self as an element of the subfield of degree n of the parent, if possible. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: z = F.gen(4) sage: (z^10)._change_level(6) 2*z6^5 + 2*z6^3 + z6^2 + 2*z6 + 2 """ F = self.parent() l = self._level m = l.gcd(n) xl = self._value xm = F.inclusion(m, l).section()(xl) xn = F.inclusion(m, n)(xm) return self.__class__(F, xn) def is_square(self): """ Return True if self is a square. This always returns True. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: F.gen(2).is_square() True """ return True def sqrt(self): """ Return a square root of self. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: F.gen(2).sqrt() z4^3 + z4 + 1 """ F = self.parent() x = self._value try: return self.__class__(F, x.sqrt(extend=False)) except ValueError: l = self._level x = F.inclusion(l, 2*l)(x) return self.__class__(F, x.sqrt(extend=False)) def unpickle_AlgebraicClosureFiniteFieldElement(parent, level, x): """ Unpickle an element x of an algebraic closure of a finite field. TEST:: sage: F = GF(7).algebraic_closure('z') sage: loads(dumps(F.gen(2))) == F.gen(2)  # indirect doctest True """ return parent.coerce(parent._subfield(level)(x)) class AlgebraicClosureFiniteField_generic(Field): """ Algebraic closure of a finite field. """ def __init__(self, base_ring, name, category=None): """ TEST:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_generic sage: F = AlgebraicClosureFiniteField_generic(GF(5), 'z') sage: F Algebraic closure of Finite Field of size 5 """ Field.__init__(self, base_ring=base_ring, names=name, normalize=False, category=category) def __getstate__(self): """ Used for pickling. TEST:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_generic sage: F = AlgebraicClosureFiniteField_generic(GF(5), 'z') sage: F.__getstate__() is None True """ pass def __setstate__(self, state): """ Used for pickling. TEST:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_generic sage: F = AlgebraicClosureFiniteField_generic(GF(5), 'z') sage: F.__setstate__(None) """ pass def __reduce__(self): """ Used for pickling. TEST:: sage: F = GF(5).algebraic_closure('z') sage: loads(dumps(F)) == F True """ return (AlgebraicClosureFiniteField, (self.base_ring(), self.variable_name(), self.category()), self.__getstate__()) def __cmp__(self, other): """ Compare self with other. TEST:: sage: F3 = GF(3).algebraic_closure('z') sage: F3 == F3 True sage: F5 = GF(5).algebraic_closure('z') sage: F3 == F5 False """ if self is other: return 0 c = cmp(type(self), type(other)) if c != 0: return c return cmp((self.base_ring(), self.variable_name(), self.category()), (other.base_ring(), other.variable_name(), other.category())) def characteristic(self): """ Return the characteristic of self. EXAMPLE:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField sage: p = next_prime(1000) sage: F = AlgebraicClosureFiniteField(GF(p), 'z') sage: F.characteristic() == p True """ return self.base_ring().characteristic() Element = AlgebraicClosureFiniteFieldElement def _element_constructor_(self, x): """ Construct an element of self. TEST:: sage: F = GF(5).algebraic_closure('z') sage: type(F(3)) """ if isinstance(x, self.element_class) and x.parent() is self: return x else: return self.element_class(self, x) def _coerce_map_from_(self, other): """ Return True if elements of other can be coerced into self. EXAMPLE:: sage: F = GF(7).algebraic_closure('z') sage: F.has_coerce_map_from(Integers()) True """ if other is self: return True elif is_FiniteField(other) and self._subfield(other.degree()) is other: return True elif self._subfield(1).has_coerce_map_from(other): return True def _repr_(self): """ Return a string representation of self. EXAMPLE:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField sage: F = AlgebraicClosureFiniteField(GF(5), 'z') sage: F._repr_() 'Algebraic closure of Finite Field of size 5' """ return 'Algebraic closure of %s' % self.base_ring() def _coerce_2(self, x, y): """ Coerce x and y to a common subfield of self. TEST:: sage: F = GF(3).algebraic_closure('z') sage: x, y = F._coerce_2(F.gen(2), F.gen(3)) sage: x.parent() Finite Field in z6 of size 3^6 sage: y.parent() Finite Field in z6 of size 3^6 """ n = x._level.lcm(y._level) mx = self.inclusion(x._level, n) my = self.inclusion(y._level, n) return mx(x._value), my(y._value) def _get_polynomial(self, n): """ Return the polynomial defining the unique subfield of degree n of self. This must be implemented by subclasses. EXAMPLE:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_generic sage: F = AlgebraicClosureFiniteField_generic(GF(5), 'z') sage: F._get_polynomial(1) Traceback (most recent call last): ... NotImplementedError """ raise NotImplementedError def _get_im_gen(self, m, n): """ Return the image of self.gen(m) under the canonical inclusion into self.subfield(n). This must be implemented by subclasses. EXAMPLE:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_generic sage: F = AlgebraicClosureFiniteField_generic(GF(5), 'z') sage: F._get_im_gen(2, 4) Traceback (most recent call last): ... NotImplementedError """ raise NotImplementedError def _subfield(self, n): """ Return the unique subfield of degree n of self. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: F._subfield(4) Finite Field in z4 of size 3^4 """ if n == 1: return self.base_ring() else: from sage.rings.finite_rings.constructor import FiniteField return FiniteField(self.base_ring().cardinality() ** n, name=self.variable_name() + str(n), modulus=self._get_polynomial(n)) def subfield(self, n): """ Return the unique subfield of degree n of self together with its canonical embedding into self. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: F.subfield(1) (Finite Field of size 3, Ring morphism: From: Finite Field of size 3 To:   Algebraic closure of Finite Field of size 3 Defn: 1 |--> 1) sage: F.subfield(4) (Finite Field in z4 of size 3^4, Ring morphism: From: Finite Field in z4 of size 3^4 To:   Algebraic closure of Finite Field of size 3 Defn: z4 |--> z4) """ Fn = self._subfield(n) return Fn, Fn.hom((self.gen(n),)) def inclusion(self, m, n): """ Return the canonical inclusion map from the subfield of degree m to the subfield of degree n. EXAMPLE:: sage: F = GF(3).algebraic_closure('z') sage: F.inclusion(1, 2) Ring Coercion morphism: From: Finite Field of size 3 To:   Finite Field in z2 of size 3^2 sage: F.inclusion(2, 4) Ring morphism: From: Finite Field in z2 of size 3^2 To:   Finite Field in z4 of size 3^4 Defn: z2 |--> 2*z4^3 + 2*z4^2 + 1 """ if m == 1: return self.base_ring().hom(self._subfield(n)) elif m.divides(n): return self._subfield(m).hom((self._get_im_gen(m, n),)) else: raise ValueError("subfield of degree %s not contained in subfield of degree %s" % (m, n)) def ngens(self): """ Return the number of generators of self, which is infinity. EXAMPLE:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField sage: AlgebraicClosureFiniteField(GF(5), 'z').ngens() +Infinity """ from sage.rings.infinity import Infinity return Infinity def gen(self, n): """ Return the n-th generator of self. EXAMPLE:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField sage: F = AlgebraicClosureFiniteField(GF(5), 'z') sage: F.gen(2) z2 """ F = self._subfield(n) return self(F.gen()) def _first_ngens(self, n): """ Return the first n generators of self. EXAMPLE:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField sage: F = AlgebraicClosureFiniteField(GF(5), 'z') sage: F._first_ngens(3) (1, z2, z3) """ return tuple([self.gen(i + 1) for i in xrange(n)]) def algebraic_closure(self): """ Return an algebraic closure of self. This always returns self. EXAMPLE:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField sage: F = AlgebraicClosureFiniteField(GF(5), 'z') sage: F.algebraic_closure() is F True """ return self class AlgebraicClosureFiniteField_pseudo_conway(AlgebraicClosureFiniteField_generic): """ Algebraic closure of a finite field, constructed using pseudo-Conway polynomials. EXAMPLE:: sage: F = GF(5).algebraic_closure('z') sage: type(F) """ def __init__(self, base_ring, name, category=None): """ TEST:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_pseudo_conway sage: F = AlgebraicClosureFiniteField_pseudo_conway(GF(3), 'z') sage: F Algebraic closure of Finite Field of size 3 """ if not (is_FiniteField(base_ring) and base_ring.is_prime_field()): raise NotImplementedError from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice self._pseudo_conway_lattice = PseudoConwayLattice(base_ring.characteristic()) AlgebraicClosureFiniteField_generic.__init__(self, base_ring, name, category) def __getstate__(self): """ Used for pickling. TEST:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_pseudo_conway sage: F = AlgebraicClosureFiniteField_pseudo_conway(GF(5), 'z') sage: F.__getstate__() """ return self._pseudo_conway_lattice def __setstate__(self, state): """ Used for pickling. TEST:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_pseudo_conway sage: F = AlgebraicClosureFiniteField_pseudo_conway(GF(5), 'z') sage: F.__setstate__(F.__getstate__()) """ self._pseudo_conway_lattice = state def __cmp__(self, other): """ Compare self with other. TEST:: sage: F3 = GF(3).algebraic_closure('z') sage: F3 == F3 True sage: F5 = GF(5).algebraic_closure('z') sage: F3 == F5 False """ c = AlgebraicClosureFiniteField_generic.__cmp__(self, other) if c != 0: return c return cmp(self._pseudo_conway_lattice, other._pseudo_conway_lattice) def _get_polynomial(self, n): """ Return the defining polynomial of the unique subfield of degree n of self. EXAMPLE:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_pseudo_conway sage: F = AlgebraicClosureFiniteField_pseudo_conway(GF(5), 'z') sage: F._get_polynomial(1) x + 3 """ return self._pseudo_conway_lattice.polynomial(n) def _get_im_gen(self, m, n): """ Return the image of self.gen(m) under the canonical inclusion into self.subfield(n). EXAMPLE:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_pseudo_conway sage: F = AlgebraicClosureFiniteField_pseudo_conway(GF(5), 'z') sage: F._get_im_gen(2, 4) z4^3 + z4^2 + z4 + 3 """ p = self.characteristic() return self._subfield(n).gen() ** ((p**n - 1)//(p**m - 1)) class AlgebraicClosureFiniteFieldFactory(UniqueFactory): """ Factory for constructing algebraic closures of finite fields. EXAMPLE:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField sage: F = GF(2).algebraic_closure('z') sage: F1 = AlgebraicClosureFiniteField(GF(2), 'z') sage: F1 is F True sage: loads(dumps(F)) is F True """ def create_key(self, base_ring, name, category=None, implementation=None, **kwds): """ TEST:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField sage: AlgebraicClosureFiniteField.create_key(GF(3), 'z') (Finite Field of size 3, 'z', Category of fields, 'pseudo_conway') """ if category is None: from sage.categories.fields import Fields category = Fields() if implementation is None: implementation = 'pseudo_conway' return (base_ring, name, category, implementation) def create_object(self, version, key, **kwds): """ TEST:: sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField sage: key = (GF(3), 'z', Fields(), 'pseudo_conway') sage: AlgebraicClosureFiniteField.create_object(0, key) Algebraic closure of Finite Field of size 3 """ base_ring, name, category, implementation = key if implementation == 'pseudo_conway': return AlgebraicClosureFiniteField_pseudo_conway(base_ring, name, category, **kwds) else: raise ValueError('unknown implementation for algebraic closure of finite field: %s' % implementation) AlgebraicClosureFiniteField = AlgebraicClosureFiniteFieldFactory('sage.rings.algebraic_closure_finite_field.AlgebraicClosureFiniteField')
• ## sage/rings/finite_rings/constructor.py

diff --git a/sage/rings/finite_rings/constructor.py b/sage/rings/finite_rings/constructor.py
 a sage: K. = GF(5**5, name='a', modulus=x^3 + 3*x + 3) Traceback (most recent call last): ... ValueError: The degree of the modulus does not correspond to the cardinality of the field. ValueError: the degree of the modulus does not equal the degree of the field. If you wish to live dangerously, you can tell the constructor not to test irreducibility using check_irreducible=False, but this if not modulus.is_irreducible(): raise ValueError("finite field modulus must be irreducible but it is not.") if modulus.degree() != n: raise ValueError("The degree of the modulus does not correspond to the cardinality of the field.") raise ValueError("the degree of the modulus does not equal the degree of the field.") if name is None: raise TypeError("you must specify the generator name.") if impl is None:
• ## sage/rings/finite_rings/conway_polynomials.py

diff --git a/sage/rings/finite_rings/conway_polynomials.py b/sage/rings/finite_rings/conway_polynomials.py
 a else: self.nodes = {} def __cmp__(self, other): """ TEST:: sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice sage: PCL3 = PseudoConwayLattice(3) sage: PCL5 = PseudoConwayLattice(5) sage: PCL3 == PCL3 True sage: PCL3 == PCL5 False """ if self is other: return 0 c = cmp(type(self), type(other)) if c != 0: return c return cmp(self.nodes, other.nodes) def polynomial(self, n): r""" Return the pseudo-Conway polynomial of degree n in this
• ## sage/rings/finite_rings/element_pari_ffelt.pyx

diff --git a/sage/rings/finite_rings/element_pari_ffelt.pyx b/sage/rings/finite_rings/element_pari_ffelt.pyx
 a pari_catch_sig_on() self.construct((x).val) else: # This is where we *would* do coercion from one finite field to another... raise TypeError("no coercion defined") elif isinstance(x, Integer):
• ## sage/rings/finite_rings/finite_field_base.pyx

diff --git a/sage/rings/finite_rings/finite_field_base.pyx b/sage/rings/finite_rings/finite_field_base.pyx
 a """ include "sage/ext/stdsage.pxi" from sage.categories.finite_fields import FiniteFields from sage.structure.parent cimport Parent from sage.misc.cachefunc import cached_method from sage.misc.prandom import randrange """ return self from sage.categories.finite_fields import FiniteFields _FiniteFields = FiniteFields() cdef class FiniteField(Field): """ Abstract base class for finite fields. """ def __init__(self, base, names, normalize): def __init__(self, base, names, normalize, category=None): """ Initialize self. sage: loads(K.dumps()) == K True """ Field.__init__(self, base, names, normalize, category=_FiniteFields) if category is None: category = FiniteFields() Field.__init__(self, base, names, normalize, category) def __repr__(self): """ ... TypeError: images do not define a valid homomorphism """ if (self.characteristic() != codomain.characteristic()): raise ValueError, "no map from %s to %s"%(self, codomain) if (len(im_gens) != 1): if not codomain.characteristic().divides(self.characteristic()): raise ValueError, "no map from %s to %s" % (self, codomain) if len(im_gens) != 1: raise ValueError, "only one generator for finite fields." return (im_gens[0].charpoly())(self.gen(0)).is_zero() return self.modulus()(im_gens[0]).is_zero() def _Hom_(self, codomain, cat=None): def _Hom_(self, codomain, category=None): """ Return homset of homomorphisms from self to the finite field codomain. This function is implicitly called by the Hom method or Return the set of homomorphisms from self to codomain in category. This function is implicitly called by the Hom method or function. The cat option is currently ignored. EXAMPLES:: sage: K. = GF(25); K Automorphism group of Finite Field in a of size 5^2 """ from sage.rings.finite_rings.homset import FiniteFieldHomset return FiniteFieldHomset(self, codomain) from sage.rings.homset import RingHomset if category.is_subcategory(FiniteFields()): return FiniteFieldHomset(self, codomain, category) else: return RingHomset(self, codomain, category) def gen(self): r""" sage: GF(997).order() 997 """ raise NotImplementedError return self.characteristic()**self.degree() def factored_order(self): """ if R.characteristic() == self.characteristic(): if R.degree() == 1: return True if self.degree() % R.degree() == 0: if hasattr(self, '_prefix') and hasattr(R, '_prefix'): return R.hom((self.gen() ** ((self.order() - 1)//(R.order() - 1)),)) elif (R.degree().divides(self.degree()) and hasattr(self, '_prefix') and hasattr(R, '_prefix')): return R.hom((self.gen() ** ((self.order() - 1)//(R.order() - 1)),)) def construction(self): """ raise ValueError, "name must be None, a string or a dictionary indexed by divisors of the degree" return [self.subfields(m, name=name[m])[0] for m in divisors] def algebraic_closure(self): def algebraic_closure(self, name): """ Return the algebraic closure of self (not implemented). Return an algebraic closure of self. INPUT: - name -- string: prefix to use for variable names of subfields EXAMPLE:: sage: F = GF(5).algebraic_closure('z') sage: F Algebraic closure of Finite Field of size 5 sage: F.gen(3) z3 .. NOTE:: This is not yet implemented for finite fields. This is currently only implemented for prime fields. EXAMPLES:: sage: GF(5).algebraic_closure() Traceback (most recent call last): ... NotImplementedError: Algebraic closures of finite fields not implemented. """ raise NotImplementedError, "Algebraic closures of finite fields not implemented." from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField return AlgebraicClosureFiniteField(self, name) @cached_method def is_conway(self):
• ## sage/rings/finite_rings/finite_field_ext_pari.py

diff --git a/sage/rings/finite_rings/finite_field_ext_pari.py b/sage/rings/finite_rings/finite_field_ext_pari.py
 a # canonically isomorphic finite fields return element_ext_pari.FiniteField_ext_pariElement(self, x) else: # This is where we *would* do coercion from one finite field to another... raise TypeError, "no coercion defined" elif sage.interfaces.gap.is_GapElement(x):
• ## sage/rings/finite_rings/finite_field_pari_ffelt.py

diff --git a/sage/rings/finite_rings/finite_field_pari_ffelt.py b/sage/rings/finite_rings/finite_field_pari_ffelt.py
 a self._modulus = modulus self._degree = n self._card = p ** n self._kwargs = {} self._gen_pari = pari(modulus).ffgen() try: return self.__hash except AttributeError: self.__hash = hash((self._card, self.variable_name(), self._modulus)) self.__hash = hash((self.cardinality(), self.variable_name(), self._modulus)) return self.__hash def __reduce__(self): """ if not isinstance(other, FiniteField_pari_ffelt): return cmp(type(self), type(other)) return cmp((self._card, self.variable_name(), self._modulus), (other._card, other.variable_name(), other._modulus)) return cmp((self.cardinality(), self.variable_name(), self._modulus), (other.cardinality(), other.variable_name(), other._modulus)) def __richcmp__(left, right, op): """ return x else: return self.element_class(self, x) def order(self): """ The number of elements of the finite field. EXAMPLE:: sage: k = FiniteField(2^10, 'a', impl='pari_ffelt') sage: k Finite Field in a of size 2^10 sage: k.order() 1024 """ return self._card
• ## sage/rings/finite_rings/finite_field_prime_modn.py

diff --git a/sage/rings/finite_rings/finite_field_prime_modn.py b/sage/rings/finite_rings/finite_field_prime_modn.py
 a _FiniteFields = FiniteFields() import sage.rings.finite_rings.integer_mod_ring as integer_mod_ring import sage.rings.integer as integer from sage.rings.integer import Integer import sage.rings.finite_rings.integer_mod as integer_mod import sage.rings.arith as arith from sage.rings.integer_ring import ZZ from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic sage: FiniteField(next_prime(1000)) Finite Field of size 1009 """ def __init__(self, p, name=None, check=True): def __init__(self, p, check=True): """ Return a new finite field of order p where p is prime. - p -- an integer at least 2 - name -- ignored - check -- bool (default: True); if False, do not check p for primality sage: F = FiniteField(3); F Finite Field of size 3 """ p = integer.Integer(p) if check and not arith.is_prime(p): p = Integer(p) if check and not p.is_prime(): raise ArithmeticError, "p must be prime" self.__char = p self._IntegerModRing_generic__factored_order = factorization.Factorization([(p,1)], integer.Integer(1)) self._IntegerModRing_generic__factored_order = factorization.Factorization([(p,1)], Integer(1)) self._kwargs = {} # FiniteField_generic does nothing more than IntegerModRing_generic, and # it saves a non trivial overhead r""" Compare self with other. Two finite prime fields are considered equal if their characteristic is equal. Two finite prime fields are considered equal if and only if their characteristics are equal. EXAMPLES:: sage: K = FiniteField(3) sage: copy(K) == K True """ if not isinstance(other, FiniteField_prime_modn): return cmp(type(self), type(other)) #        elif other.__class__ != FiniteField_prime_modn: #            return -cmp(other, self) return cmp(self.__char, other.__char) def __richcmp__(left, right, op): def modulus(self): """ Return the minimal polynomial of self, which is always x - 1. Return the defining polynomial of self. This always returns x - 1. EXAMPLES:: def gen(self, n=0): """ Return generator of this finite field as an extension of its prime field. Return a generator of self over its prime field. This always returns 1. .. NOTE:: """ if n != 0: raise IndexError, "only one generator" return self(1) return self.one_element() def __iter__(self): """ while i: yield i i += one def degree(self): """ Returns the degree of the finite field, which is a positive integer. Return the degree of self over its prime field. This always returns 1. EXAMPLES:: sage: FiniteField(3).degree() 1 """ return integer.Integer(1) return Integer(1)
• ## sage/rings/finite_rings/integer_mod.pyx

diff --git a/sage/rings/finite_rings/integer_mod.pyx b/sage/rings/finite_rings/integer_mod.pyx
 a """ return sage.rings.finite_rings.integer_mod.mod, (self.lift(), self.modulus(), self.parent()) def _im_gens_(self, codomain, im_gens): """ Return the image of self under the map that sends the generators of the parent to im_gens. EXAMPLE:: sage: a = Mod(7, 10) sage: R = ZZ.quotient(5) sage: a._im_gens_(R, (R(1),)) 2 """ return codomain._coerce_(self) def is_nilpotent(self): r""" Return True if self is nilpotent,
• ## sage/rings/residue_field.pyx

diff --git a/sage/rings/residue_field.pyx b/sage/rings/residue_field.pyx
 a # """ ResidueField_generic.__init__(self, p) FiniteField_prime_modn.__init__(self, intp, name) FiniteField_prime_modn.__init__(self, intp) from sage.rings.finite_rings.integer_mod import IntegerMod_to_IntegerMod, Integer_to_IntegerMod, Int_to_IntegerMod K = OK = p.ring() if OK.is_field():
• ## sage/structure/element.pyx

diff --git a/sage/structure/element.pyx b/sage/structure/element.pyx
 a return IS_INSTANCE(x, CommutativeRingElement) cdef class CommutativeRingElement(RingElement): def _im_gens_(self, codomain, im_gens): if len(im_gens) == 1 and self._parent.gen(0) == 1: return codomain(self) raise NotImplementedError """ Base class for elements of commutative rings. """ def inverse_mod(self, I): r""" Return an inverse of self modulo the ideal I`, if defined,