Skip to content

Commit

Permalink
extend iso_oscar_gap(FO::AnticNumberField)
Browse files Browse the repository at this point in the history
to `iso_oscar_gap(FO::NumField)`,
where the field can be simple or non-simple, absolute or non-absolute
  • Loading branch information
ThomasBreuer committed Jul 3, 2023
1 parent cff5090 commit 0be6fec
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 7 deletions.
70 changes: 66 additions & 4 deletions src/GAP/iso_oscar_gap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,8 @@ function _iso_oscar_gap_field_quadratic_functions(FO::AnticNumberField, FG::GAP.
return (f, finv)
end

function _iso_oscar_gap(FO::AnticNumberField)
# Deal with simple extensions of Q.
function _iso_oscar_gap(FO::SimpleNumField{QQFieldElem})
flag1, N1 = Hecke.is_cyclotomic_type(FO)
flag2, N2 = Hecke.is_quadratic_type(FO)
if flag1
Expand All @@ -285,16 +286,15 @@ function _iso_oscar_gap(FO::AnticNumberField)
FG = GAPWrap.Field(GAPWrap.Sqrt(GAP.Obj(N2)))
f, finv = _iso_oscar_gap_field_quadratic_functions(FO, FG)
else
polFO = FO.pol
N = degree(polFO)
polFO = defining_polynomial(FO)
coeffs_polFO = collect(coefficients(polFO))
fam = GAP.Globals.CyclotomicsFamily::GapObj
cfs = GAP.GapObj(coeffs_polFO, recursive = true)::GapObj
polFG = GAPWrap.UnivariatePolynomialByCoefficients(fam, cfs, 1)
FG = GAPWrap.AlgebraicExtension(GAP.Globals.Rationals::GapObj, polFG)
fam = GAPWrap.ElementsFamily(GAPWrap.FamilyObj(FG))

f = function(x::Nemo.nf_elem)
f = function(x::SimpleNumFieldElem{QQFieldElem})
coeffs = GAP.GapObj(coefficients(x), recursive = true)::GapObj
return GAPWrap.AlgExtElm(fam, coeffs)
end
Expand All @@ -308,6 +308,68 @@ function _iso_oscar_gap(FO::AnticNumberField)
return MapFromFunc(f, finv, FO, FG)
end

# Deal with simple extensions of proper extensions of Q.
function _iso_oscar_gap(FO::SimpleNumField{nf_elem})
B = base_field(FO)
isoB = iso_oscar_gap(B)
BG = codomain(isoB)::GapObj

polFO = defining_polynomial(FO)
coeffs_polFO = collect(coefficients(polFO))
fam = GAPWrap.ElementsFamily(GAPWrap.FamilyObj(BG))
cfs = GAP.GapObj([isoB(x) for x in coeffs_polFO])::GapObj
polFG = GAPWrap.UnivariatePolynomialByCoefficients(fam, cfs, 1)
FG = GAPWrap.AlgebraicExtension(BG, polFG)
fam = GAPWrap.ElementsFamily(GAPWrap.FamilyObj(FG))

f = function(x::SimpleNumFieldElem{nf_elem})
coeffs = GAP.GapObj([isoB(x) for x in coefficients(x)])::GapObj
return GAPWrap.AlgExtElm(fam, coeffs)
end

finv = function(x::GapObj)
coeffs = [preimage(isoB, x) for x in GapObj(GAPWrap.ExtRepOfObj(x))]
return FO(coeffs)
end

return MapFromFunc(f, finv, FO, FG)
end

# Deal with non-simple extensions of Q or of extensions of Q.
function _iso_oscar_gap(FO::NumField)
@assert ! is_simple(FO)
if is_absolute(FO)
F, emb = absolute_simple_field(FO)
else
F, emb = simple_extension(FO)
end
iso = iso_oscar_gap(F)
FG = codomain(iso)
fam = GAPWrap.ElementsFamily(GAPWrap.FamilyObj(FG))
B = base_field(F)
isoB = iso_oscar_gap(B)

f = function(x::NumFieldElem)
coeffs = GAP.GapObj([isoB(x) for x in coefficients(preimage(emb, x))])::GapObj
return GAPWrap.AlgExtElm(fam, coeffs)
end

if is_absolute(FO)
finv = function(x::GapObj)
coeffs = Vector{QQFieldElem}(GAPWrap.ExtRepOfObj(x))
return emb(F(coeffs))
end
else
finv = function(x::GapObj)
coeffs = [preimage(isoB, y) for y in GAPWrap.ExtRepOfObj(x)]
return emb(F(coeffs))
end
end

return MapFromFunc(f, finv, FO, FG)
end


# Assume that `FO` is a `QQAbField` and `FG` is `GAP.Globals.Cyclotomics`.
function _iso_oscar_gap_abelian_closure_functions(FO::QQAbField, FG::GAP.GapObj)
return (GAP.julia_to_gap, QQAbElem)
Expand Down
27 changes: 24 additions & 3 deletions test/GAP/iso_oscar_gap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ end
b = my_rand_bits(F, 5)
@test f(a*b) == f(a)*f(b)
@test f(a - b) == f(a) - f(b)
@test preimage(f, f(a)) == a
end
end
@test_throws ErrorException f(cyclotomic_field(2)[2])
Expand Down Expand Up @@ -210,6 +211,7 @@ end
b = my_rand_bits(F, 5)
@test f(a*b) == f(a)*f(b)
@test f(a - b) == f(a) - f(b)
@test preimage(f, f(a)) == a
end
end

Expand All @@ -221,11 +223,21 @@ end
@testset "number fields" begin
# for computing random elements of the fields in question
my_rand_bits(F::QQField, b::Int) = rand_bits(F, b)
my_rand_bits(F::AnticNumberField, b::Int) = F([rand_bits(QQ, b) for i in 1:degree(F)])
my_rand_bits(F::NumField, b::Int) = F([my_rand_bits(base_field(F), b) for i in 1:degree(F)])

# absolute number fields
R, x = polynomial_ring(QQ, "x")
@testset for pol in [ x^2 - 5, x^2 + 3, x^3 - 2 ]
F, z = number_field(pol)
pols = [ x^2 - 5, x^2 + 3, x^3 - 2, # simple
[x^2 - 2, x^2 + 1] ] # non-simple
fields = Any[number_field(pol)[1] for pol in pols]

# non-absolute number fields
F1, _ = number_field(x^2-2)
R1, x1 = polynomial_ring(F1, "x")
push!(fields, number_field(x1^2-3)[1]) # simple
push!(fields, number_field([x1^2-3, x1^2+1])[1]) # non-simple

@testset for F in fields
f = Oscar.iso_oscar_gap(F)
@test f === Oscar.iso_oscar_gap(F) # test that everything gets cached
for i in 1:10
Expand All @@ -234,9 +246,18 @@ end
b = my_rand_bits(F, 5)
@test f(a*b) == f(a)*f(b)
@test f(a - b) == f(a) - f(b)
@test preimage(f, f(a)) == a
end
end
end

# an application
K = fields[4]
a, b = gens(K)
M1 = 1/a*matrix(K, [1 1; 1 -1])
M2 = matrix(K, [1 0 ; 0 b])
G = matrix_group(M1, M2)
@test small_group_identification(G) == (192, 963)
end

@testset "abelian closure" begin
Expand Down

0 comments on commit 0be6fec

Please sign in to comment.