Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Add absolute_field() for finite fields
Browse files Browse the repository at this point in the history
  • Loading branch information
saraedum committed Aug 21, 2018
1 parent 23a2b10 commit 2fc28c2
Showing 1 changed file with 57 additions and 1 deletion.
58 changes: 57 additions & 1 deletion src/sage/categories/finite_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,63 @@ def _call_(self, x):
# TODO: local dvr ring?

class ParentMethods:
pass
def absolute_field(self):
r"""
Return a finite field which is isomorphic to this field together
with its isomorphisms.
The field returned is the standard ``GF(p^n)`` of Sage which might
be better suited for some computations.
OUTPUT:
A triple ``(k, f, t)`` where ``k`` is a finite field, ``f`` is an
isomorphism from ``k`` to this field, and ``t`` is an inverse of
``f``.
EXAMPLES:
A trivial case::
sage: GF(2^2).absolute_field()
Rewriting a non-standard extension::
sage: k = GF(2)
sage: R.<a> = k[]
sage: l.<a> = k.extension(a^3 + a^2 + 1)
sage: l.absolute_field()
Rewriting a tower of finite fields::
sage: R.<b> = l[]
sage: m.<b> = l.extension(b^2 + b + a)
sage: m.absolute_field()
"""
from sage.all import GF, matrix
ret = GF(self.cardinality())
if self is ret:
return ret, ret.hom(ret), ret.hom(ret)

generators = self.gens()
if len(generators) != 1:
raise NotImplementedError("finite field extension generated by more than one element in a single step; we don't know how to consistently pick the roots of these generators in the image")
generator = generators[0]

minpoly = generator.minpoly()
base_map, standard_base_to_base, base_to_standard_base = self.base_ring().absolute_field()
base_embedding = base_to_standard_base.hom(ret)
image_of_generator = minpoly.map_coefficients(base_embedding).any_root()
to_ret = self.hom([image_of_generator], base_morphism=base_embedding)

# Construct the inverse of to_ret by solving the corrspoding system
# of linear equations; we could also factor the minpoly and pick
# the right root but linear algebra is probably faster than that.
A = matrix([(image_of_generator**i)._vector_() for i in range(ret.degree())])
x = A.solve_right([i == 1 for i in range(ret.degree())])
from_ret = ret.hom([sum([c*generator**i for i,c in enumerate(x)])])
return ret, to_ret, from_ret

class ElementMethods:
pass

0 comments on commit 2fc28c2

Please sign in to comment.