From e593146a79ed7871d140ba0e44dd487c0e36be6e Mon Sep 17 00:00:00 2001 From: Tommy Hofmann Date: Wed, 7 Aug 2024 17:56:56 +0200 Subject: [PATCH] feat: improve locally free class group (#1573) - compute the idempotents in the center --- src/AlgAssAbsOrd/LocallyFreeClassGroup.jl | 17 ++++++++++- src/NumFieldOrd/NfOrd/ResidueRingMultGrp.jl | 34 ++++++++++++++++++--- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/AlgAssAbsOrd/LocallyFreeClassGroup.jl b/src/AlgAssAbsOrd/LocallyFreeClassGroup.jl index acd0db1f27..4e18fa41d7 100644 --- a/src/AlgAssAbsOrd/LocallyFreeClassGroup.jl +++ b/src/AlgAssAbsOrd/LocallyFreeClassGroup.jl @@ -233,7 +233,22 @@ function K1_order_mod_conductor(O::AlgAssAbsOrd, OA::AlgAssAbsOrd, F::AlgAssAbsO end # Make the generators coprime to the other ideals if length(moduli) != 0 # maybe O is maximal - k1 = make_coprime(elements_for_crt, moduli) + # we compute the idempotents using the ideals in the center + # and map them to the order + # this is faster than computing the idempotents in the order itself + if length(moduli) >= 2 + idemZ = _idempotents_for_make_coprime([q * OinZ for (q,_) in prim]) + idems = [O(ZtoA(elem_in_algebra.(x))) for x in idemZ] + for i in 1:length(idems) + u = idems[i] + @assert u in moduli[i] + @assert all(1 - u in moduli[j] for j in 1:length(moduli) if j != i) + end + else + # only one moduli, so no idempotent + idems = elem_type(O)[] + end + k1 = make_coprime(elements_for_crt, moduli, idems) else k1 = elem_type(O)[] end diff --git a/src/NumFieldOrd/NfOrd/ResidueRingMultGrp.jl b/src/NumFieldOrd/NfOrd/ResidueRingMultGrp.jl index f87cf937ee..a4e5435ac2 100644 --- a/src/NumFieldOrd/NfOrd/ResidueRingMultGrp.jl +++ b/src/NumFieldOrd/NfOrd/ResidueRingMultGrp.jl @@ -1170,9 +1170,20 @@ end # ################################################################################ +function _idempotents_for_make_coprime(ideals) + products = _compute_products_for_make_coprime(ideals) + n = length(ideals) + res = elem_type(order_type(algebra(ideals[1])))[] + for i = 1:n + u, v = idempotents(ideals[i], products[i]) + push!(res, u) + end + return res +end + # For an element x of elements[i] this computes an element y with # x \equiv y mod ideals[i] and x \equiv 1 mod ideals[j] for all j not equal i. -function make_coprime(elements::Vector{Vector{S}}, ideals::Vector{T}) where { S <: Union{ AbsNumFieldOrderElem, AlgAssAbsOrdElem }, T <: Union{ AbsNumFieldOrderIdeal, AlgAssAbsOrdIdl } } +function make_coprime(elements::Vector{Vector{S}}, ideals::Vector{T}, idempotents::Vector{S}) where { S <: Union{ AbsNumFieldOrderElem, AlgAssAbsOrdElem }, T <: Union{ AbsNumFieldOrderIdeal, AlgAssAbsOrdIdl } } @assert !isempty(ideals) @assert length(elements) == length(ideals) @@ -1181,20 +1192,33 @@ function make_coprime(elements::Vector{Vector{S}}, ideals::Vector{T}) where { S return elements[1] end - products = _compute_products_for_make_coprime(ideals) - One = one(order(ideals[1])) result = Vector{S}() for i = 1:n - u, v = idempotents(ideals[i], products[i]) + u = idempotents[i] + for j = 1:length(elements[i]) - t = elements[i][j] * v + One * u + t = elements[i][j] * (1 - u) + One * u push!(result, t) end end return result end +function make_coprime(elements::Vector{Vector{S}}, ideals::Vector{T}) where { S <: Union{ AbsNumFieldOrderElem, AlgAssAbsOrdElem }, T <: Union{ AbsNumFieldOrderIdeal, AlgAssAbsOrdIdl } } + @assert !isempty(ideals) + @assert length(elements) == length(ideals) + + n = length(ideals) + if n == 1 + return elements[1] + end + + idempotents = _idempotents_for_make_coprime(ideals) + + return make_coprime(elements, ideals, idempotents) +end + # Build the products \prod_{j\neq i} ideals[j] for all i function _compute_products_for_make_coprime(ideals::Vector{T}) where { T <: Union{ AbsNumFieldOrderIdeal, AlgAssAbsOrdIdl } } n = length(ideals)