using Hecke ################################################################################ # Square matrix of size n with elementary divisors A ################################################################################ function elementary_divisor_matrix(A::NfAbsOrdIdl, n::Int) OK = order(A) pm = pseudo_matrix(identity_matrix(OK,n), fill(A,n)) pm = Hecke.steinitz_form(pm) m = pm.matrix # NEW Hecke matrix(pm) m[n,:] *= isprincipal(last(pm.coeffs))[2] return m end ################################################################################ # Generators for the maximal discrete extension of the Hermitian modular group, # realized as block diagonal matrices with top left entry given by the function # below. ################################################################################ function hermitian_extension(K::AnticNumberField, n::Int) OK = maximal_order(K) clK,ψ_clK = class_group(OK) As = [] for g in gens(clK) # project to the n-torsion of the class group g = g * divexact(order(g), gcd(order(g),n)) isone(g) && continue push!(As, ψ_clK(g)) end ums = [elementary_divisor_matrix(A,n) for A in As] L = K OL = OK ms = [] for ax in 1:length(As) A = As[ax] m = elementary_divisor_matrix(A,n) Lx,x = PolynomialRing(L,"x") det_root_poly = first(factor(x^n - det(m)))[1] if degree(det_root_poly) == 1 u = -constant_coefficient(det_root_poly) else L, u = NumberField(det_root_poly, "u") L, psiL, phiL = absolute_field(L) OL = maximal_order(L) u = preimage(psiL,u) m = matrix(L,n,n,map(phiL,m)) ms = [matrix(L,n,n,map(phiL,e)) for e in ms] As = [sum(ideal(OL, OL(phiL(nf(parent(a))(a)))) for a in basis(I)) for I in As] end push!(ms, m*inv(u)) end Zx,x = PolynomialRing(ZZ,"x") p = cyclotomic(2*n,x) Lx,x = PolynomialRing(L,"x") det_root_poly = first(factor(change_base_ring(p, L, Lx)))[1] if degree(det_root_poly) != 1 L, u = NumberField(det_root_poly, "u") L, psiL, phiL = absolute_field(L) ms = [matrix(L,n,n,map(phiL,e)) for e in ms] end return (ms, ums, L) end ################################################################################ # Example matrices for the paper ################################################################################ K,a = quadratic_field(-23) n = 3 (ms,ums,L) = hermitian_extension(K,n) print(replace(replace(replace(replace(replace(replace(string(2 * ums[1]), "[" => ""), "]" => "\\\\"), "s" => "\\s"), "(" => "{"), ")" => "}"), "*" => "")) println(det(ums[1])) K,a = quadratic_field(-14) n = 4 (ms,ums,L) = hermitian_extension(K,n) print(replace(replace(replace(replace(replace(replace(string(ums[1]), "[" => ""), "]" => "\\\\"), "s" => "\\s"), "(" => "{"), ")" => "}"), "*" => "")) println(det(ums[1])) K,a = quadratic_field(-17) n = 4 (ms,ums,L) = hermitian_extension(K,n) print(replace(replace(replace(replace(replace(replace(string(ums[1]), "[" => ""), "]" => "\\\\"), "s" => "\\s"), "(" => "{"), ")" => "}"), "*" => "")) println(det(ums[1])) ################################################################################ # Collection of discriminants of extension fields ################################################################################ discs = Dict{Tuple{Int,Int},Any}() function record(d,n) K,_ = quadratic_field(d) (_,_,L) = hermitian_extension(K,n) global discs discs[n,discriminant(maximal_order(K))] = (L.pol, factor(discriminant(maximal_order(L)))) end let n = 3 for d in [-23,-31,-59,-83,-107,-139,-211,-283,-307,-331,-379,-499] record(d,n) end end let n = 4 for d in [-14,-17,-21,-30,-33,-34,-39,-42,-46,-55,- 57,-70,-73,-78,-82,-85,-93,-97,-102,-130] record(d,n) end end let n = 5 for d in [-47,-79,-103,-127,-131,-179] record(d,n) end end let n = 6 for d in [-87,-104,-116,-152,-212,-244,-247,-339,-411,-424,-436,-451,-472,-515,-628,-707] record(d,n) end end let n = 7 for d in [-71,-151,-223,-251,-463,-467,-487,-587,-811,-827,-859,-1163,-1171,-1483,-1523,-1627,-1787,-1987] record(d,n) end end ################################################################################ # Rows for the table of discriminants ################################################################################ function table_row(n,db) ds = sort([d for (ndict,d) in keys(discs) if ndict == n && d >= db]; rev=true) println(join(["\$$d\$" for d in ds] , " & ")) println("\$" * join([join(["$p^{$e}" for (p,e) in sort(collect(discs[n,d][2]))], "\\, ") for d in ds], "\$ & \$") * "\$") return (colds, coldiscs) end ################################################################################ ################################################################################ # OLD implementation of the defining fields ################################################################################ ################################################################################ function hermitian_extension_OLD(K::AnticNumberField, n::Int) OK = maximal_order(K) clK,ψ_clK = class_group(OK) clK_ntor = elem_type(clK)[] for g in gens(clK) # project to the n-torsion of the class group g = g * divexact(order(g), gcd(order(g),n)) isone(g) && continue push!(clK_ntor,g) end return [hermitian_extension_OLD(ψ_clK(g),n) for g in clK_ntor] end function hermitian_extension_OLD(A::NfAbsOrdIdl, n::Int) OK = order(A) K = number_field(OK) L,ψ_L,ϕ_L = absolute_field(number_field(hilbert_class_field(K))) OL = maximal_order(L) # NEW Hecke VERSION # A_L = ideal(OL, [OL(ϕ_L(K(a))) for a in basis(A)]) A_L = sum(ideal(OL, ϕ_L(K(a))) for a in basis(A)) A_flag, a_L = isprincipal(A_L) @assert A_flag m = elementary_divisor_matrix(A,n) v = ϕ_L(det(m)) // a_L^n # OLu, ϕ_OLu = unit_group(OL) # @info "unit" v order(preimage(ϕ_OLu, v)) == inf Lx,x = PolynomialRing(L,"x") Mpre,w = Hecke.NumberField(first(factor(x^n-v))[1],"w") M,ψ_M,ϕ_M = absolute_field(Mpre) return inv(ϕ_M(L(a_L)) * preimage(ψ_M,w)) * matrix(M, [ϕ_M(ϕ_L(m[ix,jx])) for ix in 1:n, jx in 1:n]) end