From ac039889b298700c5ef919e8d7b736db731271d9 Mon Sep 17 00:00:00 2001 From: Johannes Schmitt Date: Tue, 21 May 2024 16:43:30 +0200 Subject: [PATCH] Replace some `setprecision!(::ParentObject)` --- src/LocalField/Completions.jl | 97 +++++++------- src/LocalField/Conjugates.jl | 75 ++++++----- src/LocalField/Elem.jl | 51 ++++---- src/LocalField/LocalField.jl | 16 +-- src/LocalField/Poly.jl | 2 +- src/LocalField/automorphisms.jl | 4 +- src/LocalField/neq.jl | 170 +++++++++++++------------ src/LocalField/qAdic.jl | 5 +- src/NumField/NfAbs/MPolyAbsFact.jl | 195 +++++++++++++++-------------- src/NumField/NfAbs/PolyFact.jl | 137 +++++++++++--------- test/LocalField/LocalField.jl | 2 +- 11 files changed, 395 insertions(+), 359 deletions(-) diff --git a/src/LocalField/Completions.jl b/src/LocalField/Completions.jl index 801f3015da..2d450e99f7 100644 --- a/src/LocalField/Completions.jl +++ b/src/LocalField/Completions.jl @@ -173,9 +173,9 @@ The map giving the embedding of $K$ into the completion, admits a pointwise preimage to obtain a lift. Note, that the map is not well defined by this data: $K$ will have $\deg P$ many embeddings. -The map is guaranteed to yield a relative precision of at least `preciscion`. +The map is guaranteed to yield a relative precision of at least `precision`. """ -function completion(K::AbsSimpleNumField, P::AbsNumFieldOrderIdeal{AbsSimpleNumField, AbsSimpleNumFieldElem}, precision::Int = 64) +function completion(K::AbsSimpleNumField, P::AbsNumFieldOrderIdeal{AbsSimpleNumField, AbsSimpleNumFieldElem}, precision::Int = 64, Qp::Union{PadicField,Nothing} = nothing) #to guarantee a rel_prec we need to account for the index (or the #elementary divisor of the trace mat): the map #is for the field (equation order), the precision is measured in the @@ -189,9 +189,11 @@ function completion(K::AbsSimpleNumField, P::AbsNumFieldOrderIdeal{AbsSimpleNumF f = degree(P) e = ramification_index(P) prec_padics = div(precision+e-1, e) - Qp = padic_field(minimum(P), precision = prec_padics, cached = false) + if isnothing(Qp) + Qp = padic_field(minimum(P), precision = prec_padics, cached = false) + end Zp = maximal_order(Qp) - Qq, gQq = qadic_field(minimum(P), f, precision = prec_padics, cached = false) + Qq, gQq = unramified_extension(Qp, f, precision = prec_padics, cached = false) Qqx, gQqx = polynomial_ring(Qq, "x") q, mq = residue_field(Qq) #F, mF = ResidueFieldSmall(OK, P) @@ -264,54 +266,51 @@ function _solve_internal(gq_in_K, P, precision, Zp, Qq) mul!(bK.num, bK.num, divexact(d, denominator(bK, copy = false))) end - setprecision!(Zp, Hecke.precision(Zp) + valuation(Zp(denominator(MK)))) - -if true - #snf is slower (possibly) but has optimal precision loss. - #bad example is completion at prime over 2 in - # x^8 - 12*x^7 + 44*x^6 - 24*x^5 - 132*x^4 + 120*x^3 + 208*x^2 - 528*x + 724 - # the can_solve... returns a precision of just 6 p-adic digits - # the snf gets 16 (both for the default precision) - # the det(M) has valuation 12, but the elem. divisors only 3 - #TODO: rewrite can_solve? look at Avi's stuff? - # x M = b - # u*M*v = s - # x inv(u) u M v = b v - # x inv(u) s = b v - # x = b v inv(s) u - #lets try: - s, _u, v = snf_with_transform(MK.num) - bv = bK.num * v - bv = map_entries(Zp, bv) - for i=1:ncols(s) - bv[1, i] = divexact(bv[1, i], Zp(s[i,i])) - bv[2, i] = divexact(bv[2, i], Zp(s[i,i])) - end - xZp = bv * map_entries(Zp, _u[1:ncols(s), 1:ncols(s)]) -else - MZp = map_entries(Zp, MK.num) - bZp = map_entries(Zp, bK.num) - fl, xZp = can_solve_with_solution(MZp, bZp, side = :left) - @assert fl -end - coeffs_eisenstein = Vector{QadicFieldElem}(undef, e+1) - gQq = gen(Qq) - for i = 1:e - coeff = zero(Qq) - for j = 0:f-1 - coeff += (gQq^j)*xZp[1, j+1+(i-1)*f].x + return with_precision(Zp, Hecke.precision(Zp) + valuation(Zp(denominator(MK)))) do + if true + #snf is slower (possibly) but has optimal precision loss. + #bad example is completion at prime over 2 in + # x^8 - 12*x^7 + 44*x^6 - 24*x^5 - 132*x^4 + 120*x^3 + 208*x^2 - 528*x + 724 + # the can_solve... returns a precision of just 6 p-adic digits + # the snf gets 16 (both for the default precision) + # the det(M) has valuation 12, but the elem. divisors only 3 + #TODO: rewrite can_solve? look at Avi's stuff? + # x M = b + # u*M*v = s + # x inv(u) u M v = b v + # x inv(u) s = b v + # x = b v inv(s) u + #lets try: + s, _u, v = snf_with_transform(MK.num) + bv = bK.num * v + bv = map_entries(Zp, bv) + for i=1:ncols(s) + bv[1, i] = divexact(bv[1, i], Zp(s[i,i])) + bv[2, i] = divexact(bv[2, i], Zp(s[i,i])) + end + xZp = bv * map_entries(Zp, _u[1:ncols(s), 1:ncols(s)]) + else + MZp = map_entries(Zp, MK.num) + bZp = map_entries(Zp, bK.num) + xZp = solve(MZp, bZp, side = :left) end - coeffs_eisenstein[i] = -coeff - end - coeffs_eisenstein[e+1] = one(Qq) - if iszero(coeffs_eisenstein[1]) - error("precision not high enough to obtain Esenstein polynomial") - end - return coeffs_eisenstein, xZp + coeffs_eisenstein = Vector{QadicFieldElem}(undef, e+1) + gQq = gen(Qq) + for i = 1:e + coeff = zero(Qq) + for j = 0:f-1 + coeff += (gQq^j)*xZp[1, j+1+(i-1)*f].x + end + coeffs_eisenstein[i] = -coeff + end + coeffs_eisenstein[e+1] = one(Qq) + if iszero(coeffs_eisenstein[1]) + error("precision not high enough to obtain Esenstein polynomial") + end + return coeffs_eisenstein, xZp + end # with_precision end - - function setprecision!(f::CompletionMap{LocalField{QadicFieldElem, EisensteinLocalField}, LocalFieldElem{QadicFieldElem, EisensteinLocalField}}, new_prec::Int) P = prime(f) OK = order(P) diff --git a/src/LocalField/Conjugates.jl b/src/LocalField/Conjugates.jl index d68b62246f..363ceb389a 100644 --- a/src/LocalField/Conjugates.jl +++ b/src/LocalField/Conjugates.jl @@ -15,28 +15,26 @@ function newton_lift(f::ZZPolyRingElem, r::QadicFieldElem, prec::Int = precision o = Q(r) s = qf(r) o = inv(setprecision(qfs, 1)(o)) - @assert r.N == 1 + @assert precision(r) == 1 for p = reverse(chain) setprecision!(r, p) setprecision!(o, p) - setprecision!(Q, r.N) - if r.N > precision(Q) - setprecision!(qf, r.N) - setprecision!(qfs, r.N) + r = with_precision(Q, p) do + r - qf(r)*o end - r = r - qf(r)*o - if r.N >= n - setprecision!(Q, n) + if precision(r) >= n return r end - o = o*(2-qfs(r)*o) + o = with_precision(Q, p) do + o*(2-qfs(r)*o) + end end return r end -function newton_lift(f::ZZPolyRingElem, r::LocalFieldElem, precision::Int = precision(parent(r)), starting_prec::Int = 2) +function newton_lift(f::ZZPolyRingElem, r::LocalFieldElem, prec::Int = precision(parent(r)), starting_prec::Int = 2) Q = parent(r) - n = precision + n = prec i = n chain = [n] while i > starting_prec @@ -53,15 +51,17 @@ function newton_lift(f::ZZPolyRingElem, r::LocalFieldElem, precision::Int = prec for p = reverse(chain) r = setprecision!(r, p) o = setprecision!(o, p) - setprecision!(Q, p) setprecision!(qf, p) setprecision!(qfs, p) - r = r - qf(r)*o - if Nemo.precision(r) >= n - setprecision!(Q, n) + r = with_precision(Q, p) do + return r - qf(r)*o + end + if precision(r) >= n return r end - o = o*(2-qfs(r)*o) + o = with_precision(Q, p) do + return o*(2-qfs(r)*o) + end end return r end @@ -93,10 +93,11 @@ function roots(C::qAdicRootCtx, n::Int = 10) lf = factor_mod_pk(Array, C.H, n) rt = QadicFieldElem[] for Q = C.Q - setprecision!(Q, n) for x = lf if is_splitting(C) || degree(x[1]) == degree(Q) - append!(rt, roots(Q, x[1], max_roots = 1)) + with_precision(Q, n) do + append!(rt, roots(Q, x[1], max_roots = 1)) + end end end end @@ -222,12 +223,14 @@ end function _conjugates(a::AbsSimpleNumFieldElem, C::qAdicConj, n::Int, op::Function) R = roots(C.C, n) @assert parent(a) == C.K - Zx = polynomial_ring(FlintZZ, cached = false)[1] + Zx = polynomial_ring(ZZ, cached = false)[1] d = denominator(a) f = Zx(d*a) res = QadicFieldElem[] for x = R - a = op(inv(parent(x)(d))*f(x))::QadicFieldElem + a = with_precision(parent(x), n) do + op(inv(parent(x)(d))*f(x))::QadicFieldElem + end push!(res, a) end return res @@ -272,11 +275,13 @@ function conjugates_log(a::FacElem{AbsSimpleNumFieldElem, AbsSimpleNumField}, C: for (k, v) = a.fac try y = conjugates_log(k, C, n, flat = false, all = false) + # vy = v .* y but we need to be careful with the precision of v + vy = QadicFieldElem[parent(yy)(v, precision = n) * yy for yy in y] if first - res = v .* y + res = vy first = false else - res += v .* y + res += vy end catch e if isa(e, DivideError) || isa(e, DomainError) @@ -286,11 +291,13 @@ function conjugates_log(a::FacElem{AbsSimpleNumFieldElem, AbsSimpleNumField}, C: pe = prod(lp[i][1].gen_two^val[i] for i = 1:length(lp) if val[i] != 0) aa = k//pe y = conjugates_log(aa, C, n, all = false, flat = false) + # vy = v .* y but we need to be careful with the precision of v + vy = QadicFieldElem[parent(yy)(v, precision = n) * yy for yy in y] if first - res = v .* y + res = vy first = false else - res += v .* y + res += vy end else rethrow(e) @@ -308,18 +315,22 @@ end function special_gram(m::Vector{Vector{QadicFieldElem}}) g = Vector{PadicFieldElem}[] + if isempty(m) + return g + end + K = base_field(parent(m[1][1])) for i = m r = PadicFieldElem[] for j = m k = 1 - S = 0 + S = K() while k <= length(i) s = i[k] * j[k] for l = 1:degree(parent(s))-1 s += i[k+l] * j[k+l] end S += coeff(s, 0) - @assert s == coeff(s, 0) + @assert length(s) == 1 k += degree(parent(s)) end push!(r, S) @@ -347,7 +358,11 @@ In either case, Leopold's conjecture states that the regulator is zero iff the u """ function regulator(u::Vector{T}, C::qAdicConj, n::Int = 10; flat::Bool = true) where {T<: Union{AbsSimpleNumFieldElem, FacElem{AbsSimpleNumFieldElem, AbsSimpleNumField}}} c = map(x -> conjugates_log(x, C, n, all = !flat, flat = flat), u) - return det(transpose(matrix(special_gram(c)))) + K = base_field(parent(c[1][1])) + sg = with_precision(K, n) do + special_gram(c) + end + return det(transpose(matrix(sg))) end function regulator(K::AbsSimpleNumField, C::qAdicConj, n::Int = 10; flat::Bool = false) @@ -529,6 +544,8 @@ function completion(K::AbsSimpleNumField, p::ZZRingElem, i::Int, n = 64) @assert 0parent(r[x]) == parent(ca) && r[x] == ca, 1:length(r)) - Zx = polynomial_ring(FlintZZ, cached = false)[1] + Zx = polynomial_ring(ZZ, cached = false)[1] function inj(a::AbsSimpleNumFieldElem) d = denominator(a) pr = precision(parent(ca)) @@ -564,7 +581,7 @@ function completion(K::AbsSimpleNumField, ca::QadicFieldElem) for i=1:d _num_setcoeff!(a, i-1, lift(ZZ, s[i, 1])) end - f = defining_polynomial(parent(ca), FlintZZ) + f = defining_polynomial(parent(ca), ZZ) fso = inv(derivative(f)(gen(R))) o = matrix(GF(p), d, 1, [lift(ZZ, coeff(fso, j-1)) for j=1:d]) s = solve(m, o; side = :right) diff --git a/src/LocalField/Elem.jl b/src/LocalField/Elem.jl index d0c6fc347e..da61d3d7d5 100644 --- a/src/LocalField/Elem.jl +++ b/src/LocalField/Elem.jl @@ -448,7 +448,7 @@ function norm(a::LocalFieldElem) return AbstractAlgebra.det_df(representation_matrix(a)) #the resultant is not quite stable (yet), it is not using the #fun factor stuff... - res = setprecision(base_ring(a.data), precision(a.data)) do + res = with_precision(base_ring(a.data), precision(a.data)) do resultant(defining_polynomial(K, precision(a.data)), a.data) end return res @@ -573,7 +573,7 @@ end function Base.:+(a::LocalFieldElem{S, T}, b::LocalFieldElem{S, T}) where {S <: FieldElem, T <: LocalFieldParameter} check_parent(a, b) K = parent(a) - c = setprecision(base_ring(a.data), _precision_base(K)) do + c = with_precision(base_ring(a.data), _precision_base(K)) do a.data + b.data end return LocalFieldElem{S, T}(parent(a), c, min(precision(a), precision(b))) @@ -582,7 +582,7 @@ end function Base.:-(a::LocalFieldElem{S, T}, b::LocalFieldElem{S, T}) where {S <: FieldElem, T <: LocalFieldParameter} check_parent(a, b) K = parent(a) - c = setprecision(base_ring(a.data), _precision_base(K)) do + c = with_precision(base_ring(a.data), _precision_base(K)) do a.data - b.data end return LocalFieldElem{S, T}(parent(a), c, min(precision(a), precision(b))) @@ -646,14 +646,14 @@ function mul!(c::LocalFieldElem{S, T}, a::LocalFieldElem{S, T}, b::LocalFieldEle end function uniformizer(L::Union{PadicField, QadicField}, v::Int; prec::Int = 20) #precision???? - return setprecision(L, prec) do + return with_precision(L, prec) do uniformizer(L)^v end end function uniformizer(L::LocalField, v::Int; prec::Int = 20) #precision???? if v > 0 - return setprecision(L, prec) do + return with_precision(L, prec) do uniformizer(L)^v end end @@ -669,7 +669,7 @@ function uniformizer(L::LocalField, v::Int; prec::Int = 20) #precision???? pr = ceil(Int, (prec-v)/e)+2 f = defining_polynomial(L, pr) local pi_inv - setprecision(L, pr*e) do + with_precision(L, pr*e) do g = parent(f)([coeff(f, i) for i=1:degree(f)]) pi_inv = g(uniformizer(L)) pi_inv *= -inv(coeff(f, 0)) @@ -714,7 +714,7 @@ function Base.:(^)(a::LocalFieldElem, n::Int) else b = data(a) end - b = setprecision(base_ring(b), prec) do + b = with_precision(base_ring(b), prec) do powermod(b, n, defining_polynomial(K, prec)) end return K(b) @@ -750,20 +750,20 @@ function exp(a::LocalFieldElem) N = N_orig + clog(ZZRingElem(N_orig), p) a = setprecision(a, N) oN = precision(parent(a)) - setprecision!(parent(a), max(oN, N)) - res = one(K, precision = N) - el = one(K) - den = one(Qp, precision = N) - #precision is suboptimal, its truncated badly, thus losing it - max_i = QQFieldElem(N)//(valuation(a) - QQFieldElem(1, p-1)) + 1 - bound = Int(floor(ZZRingElem, max_i)) - for i = 1:bound - el *= a//i - res += el - end - setprecision!(res, N_orig) - setprecision!(parent(a), oN) - return res + return with_precision(parent(a), max(oN, N)) do + res = one(K, precision = N) + el = one(K) + den = one(Qp, precision = N) + #precision is suboptimal, its truncated badly, thus losing it + max_i = QQFieldElem(N)//(valuation(a) - QQFieldElem(1, p-1)) + 1 + bound = Int(floor(ZZRingElem, max_i)) + for i = 1:bound + el *= a//i + res += el + end + setprecision!(res, N_orig) + return res + end # with_precision end ################################################################################ @@ -857,16 +857,15 @@ function divexact(a::LocalFieldElem, b::Union{Integer, ZZRingElem}; check::Bool= v = valuation(b, p) iszero(a) && return setprecision(a, precision(a) - v*e) Qp = absolute_base_field(K) - old = precision(Qp) - setprecision!(Qp, e*precision(a)+ Int(_valuation_integral(a)) + v) - bb = inv(Qp(b)) - setprecision!(Qp, old) + bb = with_precision(Qp, e*precision(a) + Int(_valuation_integral(a)) + v) do + return inv(Qp(b)) + end return a*bb end function _log_one_units_fast(a::LocalFieldElem) K = parent(a) - fl, b = setprecision(K, precision(a)) do + fl, b = with_precision(K, precision(a)) do if isone(a) || iszero(a - 1) return true, zero(K) end diff --git a/src/LocalField/LocalField.jl b/src/LocalField/LocalField.jl index c38ef7f6a7..caafaa4443 100644 --- a/src/LocalField/LocalField.jl +++ b/src/LocalField/LocalField.jl @@ -386,18 +386,20 @@ function setprecision!(K::LocalField, n::Int) return nothing end -function setprecision(f::Function, K::Union{LocalField, PadicField, QadicField}, n::Int) +function with_precision(f, K::LocalField, n::Int) + @assert n >= 0 old = precision(K) -# @assert n>=0 setprecision!(K, n) v = try - setprecision(f, base_field(K), ceil(Int, n/ramification_index(K))) - finally - setprecision!(K, old) - end + with_precision(f, base_field(K), ceil(Int, n/ramification_index(K))) + finally + setprecision!(K, old) + end return v end +setprecision(f, K::LocalField, n::Int) = with_precision(f, K, n) + ################################################################################ # # Uniformizer @@ -489,7 +491,7 @@ end ################### unramified extension over local field L of a given degree n #################### - function unramified_extension(L::Union{PadicField, QadicField, LocalField}, n::Int) + function unramified_extension(L::Union{QadicField, LocalField}, n::Int) R, mR = residue_field(L) Rt, t = polynomial_ring(R, "t", cached = false) f = Rt(push!([rand(R) for i = 0:n-1], one(R))) diff --git a/src/LocalField/Poly.jl b/src/LocalField/Poly.jl index 0548396070..79734e5668 100644 --- a/src/LocalField/Poly.jl +++ b/src/LocalField/Poly.jl @@ -926,7 +926,7 @@ function lift(C::HenselCtxdr, mx::Int) N = minimum([precision(x) for x in C.lf]) N = min(N, minimum([precision(x) for x in C.la])) #have: N need mx - one = setprecision(parent(p), mx) do + one = with_precision(parent(p), mx) do Base.one(parent(p)) end ch = Int[mx] diff --git a/src/LocalField/automorphisms.jl b/src/LocalField/automorphisms.jl index e3f697208c..c7d7f571c0 100644 --- a/src/LocalField/automorphisms.jl +++ b/src/LocalField/automorphisms.jl @@ -106,7 +106,9 @@ function _roots(f::Generic.Poly{T}) where T <: Union{PadicFieldElem, QadicFieldE end function automorphism_list(K::T) where T <: Union{LocalField, QadicField} - f = map_coefficients(K, defining_polynomial(K), cached = false) + f = with_precision(base_field(K), precision(K)) do + map_coefficients(K, defining_polynomial(K), cached = false) + end rt = roots(f) rt = refine_roots1(f, rt) diff --git a/src/LocalField/neq.jl b/src/LocalField/neq.jl index 2f13281b24..ac3dd96191 100644 --- a/src/LocalField/neq.jl +++ b/src/LocalField/neq.jl @@ -109,7 +109,7 @@ function h2_is_iso(K::Hecke.LocalField) k, mk = residue_field(K) pi = uniformizer(K) pi = setprecision(pi, 2*e) - eps = setprecision(K, precision(K)+e) do + eps = with_precision(K, precision(K)+e) do -inv(divexact(pi^e, p)) end #assert valuation(eps) == 0 @@ -147,7 +147,7 @@ function _unit_group_gens_case2(K::Union{QadicField, Hecke.LocalField}) #we need p/pi^e, the unit, with enough precision, #precision(eps) = k -> p, pi needs 2k pi = setprecision(pi, precision(K)+2*e) - eps = setprecision(K, precision(K)+e) do + eps = with_precision(K, precision(K)+e) do -inv(divexact(pi^e, p)) end # @assert precision(eps) >= precision(K) # does not (quite) work @@ -232,92 +232,90 @@ function solve_1_units(a::Vector{T}, b::T) where T #Z_p (and Z) operates on the 1-units... k = precision(b) K = parent(b) - old = precision(K) - setprecision!(K, k) - one = K(1) - if iszero(b-one) - setprecision!(K, old) - return ZZRingElem[0 for i=a], ZZRingElem(1) - end - @assert valuation(b-one) > 0 - @assert all(x->parent(x) == K , a) - #plan: - # (1+p^k/1+p^l, *) = (p^k/p^l, +) for k<=l<=2k - #so we start with k=1, l=2 to find the exponents mod p - #remove this from b - #try to find the next part (mod p^2), ... - # - e = absolute_ramification_index(K) - f = absolute_inertia_degree(K) - pi = uniformizer(K) - p = prime(K) - l = 1 - cur_a = copy(a) - cur_b = b -# @assert degree(K) == e - Qp = absolute_base_field(K) - Zp = ring_of_integers(Qp) - expo_mult = identity_matrix(ZZ, length(cur_a)) - #transformation of cur_a to a - expo = zero_matrix(ZZ, 1, length(cur_a)) - pk = ZZRingElem(p) - - val_offset = e .* map(valuation, absolute_basis(K)) - pow_b = ZZRingElem(1) - - while l <= k -# @show 1, l, pow_b, k, expo - last_val = e*valuation(cur_b-one) -# @show expo_mult - @assert e*valuation(cur_b-one) >= l - @assert all(x->isone(x) || e*valuation(x-one) >= l, cur_a) - - A = abelian_group([p^max(0, ceil(Int, (l-v)//e)) for v = val_offset]) - h = hom(free_abelian_group(length(cur_a)), A, [A([lift(ZZ, x) for x = absolute_coordinates(divexact(y-one, pi^l))]) for y = cur_a]) - lhs = A([lift(ZZ, x) for x = absolute_coordinates(divexact(cur_b -one, pi^l))]) - fl, s = has_preimage_with_preimage(h, lhs) - _k, _mk = kernel(h) - #if kernel has HNF, the next step is cheaper... - _mk.map = hnf(_mk.map) - #to find a nice preimage - reduce_mod_hnf_ur!(s.coeff, _mk.map) -# @show s - # to verify that this is a "legal" operation... the hom constructor - # will verify that this is legal - # hom(domain(_mk), codomain(_mk), [_mk(x) for x = gens(domain(_mk))]) - - if !fl - pow_b *= p - cur_b = cur_b^p - expo = expo * p - if iszero(cur_b-one) - break - end - last_val = e*valuation(cur_b-one) - continue + return with_precision(K, k) do + one = K(1) + if iszero(b-one) + return ZZRingElem[0 for i=a], ZZRingElem(1) end + @assert valuation(b-one) > 0 + @assert all(x->parent(x) == K , a) + #plan: + # (1+p^k/1+p^l, *) = (p^k/p^l, +) for k<=l<=2k + #so we start with k=1, l=2 to find the exponents mod p + #remove this from b + #try to find the next part (mod p^2), ... + # + e = absolute_ramification_index(K) + f = absolute_inertia_degree(K) + pi = uniformizer(K) + p = prime(K) + l = 1 + cur_a = copy(a) + cur_b = b +# @assert degree(K) == e + Qp = absolute_base_field(K) + Zp = ring_of_integers(Qp) + expo_mult = identity_matrix(ZZ, length(cur_a)) + #transformation of cur_a to a + expo = zero_matrix(ZZ, 1, length(cur_a)) + pk = ZZRingElem(p) + + val_offset = e .* map(valuation, absolute_basis(K)) + pow_b = ZZRingElem(1) + + while l <= k +# @show 1, l, pow_b, k, expo + last_val = e*valuation(cur_b-one) +# @show expo_mult + @assert e*valuation(cur_b-one) >= l + @assert all(x->isone(x) || e*valuation(x-one) >= l, cur_a) + + A = abelian_group([p^max(0, ceil(Int, (l-v)//e)) for v = val_offset]) + h = hom(free_abelian_group(length(cur_a)), A, [A([lift(ZZ, x) for x = absolute_coordinates(divexact(y-one, pi^l))]) for y = cur_a]) + lhs = A([lift(ZZ, x) for x = absolute_coordinates(divexact(cur_b -one, pi^l))]) + fl, s = has_preimage_with_preimage(h, lhs) + _k, _mk = kernel(h) + #if kernel has HNF, the next step is cheaper... + _mk.map = hnf(_mk.map) + #to find a nice preimage + reduce_mod_hnf_ur!(s.coeff, _mk.map) +# @show s + # to verify that this is a "legal" operation... the hom constructor + # will verify that this is legal + # hom(domain(_mk), codomain(_mk), [_mk(x) for x = gens(domain(_mk))]) + + if !fl + pow_b *= p + cur_b = cur_b^p + expo = expo * p + if iszero(cur_b-one) + break + end + last_val = e*valuation(cur_b-one) + continue + end - expo += s.coeff * expo_mult - expo_mult = reduce(vcat, [_mk(x).coeff for x = gens(_k)])*expo_mult - cur_a = [prod(cur_a[i]^_mk(x)[i] for i=1:length(cur_a)) for x = gens(_k)] -# @show [e*valuation(x-1) for x = cur_a] + expo += s.coeff * expo_mult + expo_mult = reduce(vcat, [_mk(x).coeff for x = gens(_k)])*expo_mult + cur_a = [prod(cur_a[i]^_mk(x)[i] for i=1:length(cur_a)) for x = gens(_k)] +# @show [e*valuation(x-1) for x = cur_a] - cur_b = divexact(b^pow_b, prod(a[i]^expo[i] for i=1:length(a))) - if iszero(cur_b-one) || e*valuation(cur_b-one) >= k - break - end -# @show e*valuation(cur_b-one), 2l-1, last_val, k - @assert e*valuation(cur_b-one) >= min(2*l-1, last_val) - last_val = e*valuation(cur_b-one) + cur_b = divexact(b^pow_b, prod(a[i]^expo[i] for i=1:length(a))) + if iszero(cur_b-one) || e*valuation(cur_b-one) >= k + break + end +# @show e*valuation(cur_b-one), 2l-1, last_val, k + @assert e*valuation(cur_b-one) >= min(2*l-1, last_val) + last_val = e*valuation(cur_b-one) - if l == k - break + if l == k + break + end + l *= 2 + l = min(l, k) end - l *= 2 - l = min(l, k) - end - setprecision!(K, old) - return [expo[1, i] for i=1:length(cur_a)], pow_b + return [expo[1, i] for i=1:length(cur_a)], pow_b + end # with_precision end function is_norm(K::Hecke.LocalField, b::Union{QadicFieldElem,PadicFieldElem,Hecke.LocalFieldElem}) @@ -368,7 +366,7 @@ function _norm_equation(K:: Hecke.LocalField, b::Union{QadicFieldElem,PadicField # - if v(b-1) > 1/(p-1), then exp/log work and we can reduce # to trace equation.. bb = setprecision(b, ceil(Int, e//(p-1))) - g = setprecision(K, precision(bb)*ramification_index(K)) do + g = with_precision(K, precision(bb)*ramification_index(K)) do one_unit_group_gens(K) end ng = map(norm, g) @@ -617,7 +615,7 @@ function frobenius_equation(c::Hecke.LocalFieldElem, F::Union{PadicField, QadicF end v_deg = valuation(absolute_degree(E), prime(E)) - setprecision(E, precision(E) + v_deg) do + with_precision(E, precision(E) + v_deg) do c = setprecision(c, precision(E)) cnt = 0 while true @@ -649,7 +647,7 @@ function frobenius_equation(c::Hecke.LocalFieldElem, F::Union{PadicField, QadicF return frobenius_equation2(c, F, frobenius = fr) end end - end #setprecision + end # with_precision end #solve the same as above, but pi-adic digit by pi-adic digit, thus diff --git a/src/LocalField/qAdic.jl b/src/LocalField/qAdic.jl index db27c0bd1c..5767cda114 100644 --- a/src/LocalField/qAdic.jl +++ b/src/LocalField/qAdic.jl @@ -81,7 +81,6 @@ function lift_reco(::QQField, a::PadicFieldElem; reco::Bool = false) end end - uniformizer(Q::QadicField) = Q(prime(Q)) uniformizer(Q::PadicField) = Q(prime(Q)) @@ -89,10 +88,10 @@ uniformizer(Q::PadicField) = Q(prime(Q)) function defining_polynomial(Q::QadicField, P::Ring = base_field(Q)) Pt, t = polynomial_ring(P, cached = false) f = Pt() - for i=0:Q.len-1 + for i in 0:Q.len-1 j = unsafe_load(reinterpret(Ptr{Int}, Q.j), i+1) a = ZZRingElem() - ccall((:fmpz_set, libflint), Nothing, (Ref{ZZRingElem}, Int64), a, Q.a+i*sizeof(Ptr)) + ccall((:fmpz_set, libflint), Nothing, (Ref{ZZRingElem}, Int64), a, Q.a + i*sizeof(Ptr)) setcoeff!(f, j, P(a)) end return f diff --git a/src/NumField/NfAbs/MPolyAbsFact.jl b/src/NumField/NfAbs/MPolyAbsFact.jl index 00bed7e6c5..fb56569ca1 100644 --- a/src/NumField/NfAbs/MPolyAbsFact.jl +++ b/src/NumField/NfAbs/MPolyAbsFact.jl @@ -333,61 +333,61 @@ function lift_q(C::HenselCtxFqRelSeries{<:SeriesElem{QadicFieldElem}}) pr = precision(coeff(coeff(C.lf[1], 0), 0)) N2 = 2*pr - setprecision!(Q, N2) - - i = length(C.lf) - @assert i > 1 - @assert all(is_monic, C.lf[1:end-1]) - j = i-1 - while j > 0 - if i==length(C.lf) - f = evaluate(map_coefficients(Q, C.f, cached = false), [gen(St), St(gen(S))]) - f *= inv(leading_coefficient(f)) - else -# f = _set_precision(C.lf[i], N2) - f = C.lf[i] - @assert precision(coeff(coeff(f, 0), 0)) >= N2 - @assert is_monic(C.lf[i]) - end - @assert is_monic(f) - #formulae and names from the Flint doc - h = C.lf[j] - g = C.lf[j-1] - b = C.cf[j] - a = C.cf[j-1] - h = _set_precision(h, N2) - g = _set_precision(g, N2) - a = _set_precision(a, N2) - b = _set_precision(b, N2) - - fgh = _shift_coeff_right(f-g*h, pr) - - @assert is_monic(g) - @assert !iszero(constant_coefficient(g)) - @assert is_monic(h) - @assert !iszero(constant_coefficient(h)) - gi = preinv(g) - hi = preinv(h) - - G = _shift_coeff_left(rem(fgh*b, gi), pr)+g - @assert is_monic(G) - H = _shift_coeff_left(rem(fgh*a, hi), pr)+h - @assert is_monic(H) + return with_precision(Q, N2) do + i = length(C.lf) + @assert i > 1 + @assert all(is_monic, C.lf[1:end-1]) + j = i-1 + while j > 0 + if i==length(C.lf) + f = evaluate(map_coefficients(Q, C.f, cached = false), [gen(St), St(gen(S))]) + f *= inv(leading_coefficient(f)) + else +# f = _set_precision(C.lf[i], N2) + f = C.lf[i] + @assert precision(coeff(coeff(f, 0), 0)) >= N2 + @assert is_monic(C.lf[i]) + end + @assert is_monic(f) + #formulae and names from the Flint doc + h = C.lf[j] + g = C.lf[j-1] + b = C.cf[j] + a = C.cf[j-1] + h = _set_precision(h, N2) + g = _set_precision(g, N2) + a = _set_precision(a, N2) + b = _set_precision(b, N2) + + fgh = _shift_coeff_right(f-g*h, pr) + + @assert is_monic(g) + @assert !iszero(constant_coefficient(g)) + @assert is_monic(h) + @assert !iszero(constant_coefficient(h)) + gi = preinv(g) + hi = preinv(h) + + G = _shift_coeff_left(rem(fgh*b, gi), pr)+g + @assert is_monic(G) + H = _shift_coeff_left(rem(fgh*a, hi), pr)+h + @assert is_monic(H) - t = _shift_coeff_right(1-a*G-b*H, pr) + t = _shift_coeff_right(1-a*G-b*H, pr) - B = _shift_coeff_left(rem(t*b, gi), pr)+b - A = _shift_coeff_left(rem(t*a, hi), pr)+a -# check_data(A) -# check_data(B) + B = _shift_coeff_left(rem(t*b, gi), pr)+b + A = _shift_coeff_left(rem(t*a, hi), pr)+a +# check_data(A) +# check_data(B) - C.lf[j-1] = G - C.lf[j] = H - C.cf[j-1] = A - C.cf[j] = B - i -= 1 - j -= 2 - end + C.lf[j-1] = G + C.lf[j] = H + C.cf[j-1] = A + C.cf[j] = B + i -= 1 + j -= 2 + end + end # with_precision end mutable struct RootCtxSingle{T} @@ -1025,42 +1025,43 @@ function field(RC::RootCtx, m::MatElem) end @vprintln :AbsFact 1 "using p-adic precision of $pr" - setprecision!(Qq, pr+1) - if length(fa) > 0 - H.f = map_coefficients(Qq, _lc, parent = Qqt) - @vprintln :AbsFact 2 "lifting leading coeff factorisation" - @vtime :AbsFact 2 Hecke.lift(H, pr+1) - fH = factor(H) - lc = [prod(fH[i]^t[i] for i=1:length(t)) for t = fa] - end + p, el, fl = with_precision(Qq, pr + 1) do + if length(fa) > 0 + H.f = map_coefficients(Qq, _lc, parent = Qqt) + @vprintln :AbsFact 2 "lifting leading coeff factorisation" + @vtime :AbsFact 2 Hecke.lift(H, pr+1) + fH = factor(H) + lc = [prod(fH[i]^t[i] for i=1:length(t)) for t = fa] + end - @vprintln :AbsFact 1 "lifting factors" - @vtime :AbsFact 2 while precision(coeff(coeff(HQ.lf[1], 0), 0)) < pr+1 - lift_q(HQ) - end + @vprintln :AbsFact 1 "lifting factors" + @vtime :AbsFact 2 while precision(coeff(coeff(HQ.lf[1], 0), 0)) < pr+1 + lift_q(HQ) + end - if length(fa) > 0 - z = [lc[i](gen(SQq)) * HQ.lf[i] for i=1:HQ.n] - else - z = HQ.lf[1:HQ.n] - end + if length(fa) > 0 + z = [lc[i](gen(SQq)) * HQ.lf[i] for i=1:HQ.n] + else + z = HQ.lf[1:HQ.n] + end - setprecision!(coeff(X, 1), pr+2) - setprecision!(coeff(Y, 1), pr+2) - el = [map_coefficients(q -> lift(Qqt, q)(Y), f, cached = false)(X) for f = z] + setprecision!(coeff(X, 1), pr+2) + setprecision!(coeff(Y, 1), pr+2) + el = [map_coefficients(q -> lift(Qqt, q)(Y), f, cached = false)(X) for f = z] -# # lift mod p^1 -> p^pr x^2+y^2+px+1 was bad I think -# @vtime :AbsFact 1 ok, el = lift_prime_power(P*inv(coeff(P, 1)), el, [0], 1, pr) -# ok || @vprintln :AbsFact 1 "bad prime found, q-adic lifting failed" -# ok || return nothing -# @assert ok # can fail but should fail for only finitely many p +# # lift mod p^1 -> p^pr x^2+y^2+px+1 was bad I think +# @vtime :AbsFact 1 ok, el = lift_prime_power(P*inv(coeff(P, 1)), el, [0], 1, pr) +# ok || @vprintln :AbsFact 1 "bad prime found, q-adic lifting failed" +# ok || return nothing +# @assert ok # can fail but should fail for only finitely many p - #to make things integral... - fl = Qq(llc) .* el + #to make things integral... + fl = Qq(llc) .* el - p = [coeff(sum(pe(x)^l for x = fl), 0) for l=1:length(el)] - p = map(rational_reconstruction, p) + p = [coeff(sum(pe(x)^l for x = fl), 0) for l=1:length(el)] + return map(rational_reconstruction, p), el, fl + end # with_precision if !all(x->x[1], p) @vprintln :AbsFact 2 "reco failed (for poly), increasing p-adic precision" @@ -1083,25 +1084,27 @@ function field(RC::RootCtx, m::MatElem) @vprintln :AbsFact 1 "using as number field: $k" - m = transpose(matrix([[pe(x)^l for x = fl] for l=0:degree(k)-1])) - kx, x = polynomial_ring(k, "x", cached = false) - kX, _ = polynomial_ring(k, ["X", "Y"], cached = false) - B = MPolyBuildCtx(kX) - for j=1:length(el[1]) - n = transpose(matrix([[coeff(x, j)] for x = fl])) - s = Hecke.solve(m, transpose(n); side = :right) - @assert all(x->iszero(coeff(s[x, 1], 1)), 1:degree(k)) - s = [rational_reconstruction(coeff(s[i, 1], 0)) for i=1:degree(k)] - if !all(x->x[1], s) - break + q = with_precision(Qq, pr+1) do + m = transpose(matrix([[pe(x)^l for x = fl] for l=0:degree(k)-1])) + kx, x = polynomial_ring(k, "x", cached = false) + kX, _ = polynomial_ring(k, ["X", "Y"], cached = false) + B = MPolyBuildCtx(kX) + for j=1:length(el[1]) + n = transpose(matrix([[coeff(x, j)] for x = fl])) + s = Hecke.solve(m, transpose(n); side = :right) + @assert all(x->iszero(coeff(s[x, 1], 1)), 1:degree(k)) + s = [rational_reconstruction(coeff(s[i, 1], 0)) for i=1:degree(k)] + if !all(x->x[1], s) + break + end + push_term!(B, k([x[2]//x[3] for x = s]), exponent_vector(el[1], j)) end - push_term!(B, k([x[2]//x[3] for x = s]), exponent_vector(el[1], j)) - end - q = finish(B) + return finish(B) + end # with_precision if length(q) < length(el[1]) continue end - b, r = divrem(map_coefficients(k, P, parent = kX), [q]) + b, r = divrem(map_coefficients(k, P, parent = parent(q)), [q]) if iszero(r) return q, b[1] end diff --git a/src/NumField/NfAbs/PolyFact.jl b/src/NumField/NfAbs/PolyFact.jl index 2a38a9c8df..e3c99880b8 100644 --- a/src/NumField/NfAbs/PolyFact.jl +++ b/src/NumField/NfAbs/PolyFact.jl @@ -59,8 +59,9 @@ function lift(C::HenselCtxQadic, mx::Int = minimum(precision, coefficients(C.f)) @vprintln :PolyFactor 1 "using lifting chain $ch" for k=length(ch)-1:-1:1 N2 = ch[k] - setprecision!(Q, N2+1) - p = Q(prime(Q))^ch[k+1] + p = with_precision(Q, N2 + 1) do + Q(prime(Q))^ch[k+1] + end i = length(C.lf) j = i-1 p = setprecision(p, N2) @@ -84,7 +85,9 @@ function lift(C::HenselCtxQadic, mx::Int = minimum(precision, coefficients(C.f)) fgh = (f-g*h)*inv(p) G = rem(fgh*b, g)*p+g H = rem(fgh*a, h)*p+h - t = (1-a*G-b*H)*inv(p) + t = with_precision(Q, N2 + 1) do + (1-a*G-b*H)*inv(p) + end B = rem(t*b, g)*p+b A = rem(t*a, h)*p+a if i < length(C.lf) @@ -98,7 +101,10 @@ function lift(C::HenselCtxQadic, mx::Int = minimum(precision, coefficients(C.f)) j -= 2 end end - C.p = Q(prime(Q))^ch[1] + C.p = with_precision(Q, ch[1] + 1) do + Q(prime(Q))^ch[1] + end + return C.p end function factor(C::HenselCtxQadic) @@ -357,32 +363,34 @@ function zassenhaus(f::PolyRingElem{AbsSimpleNumFieldElem}, P::AbsNumFieldOrderI N = ceil(Int, degree(K)/2/log(norm(P))*(log2(c1*c2) + 2*nbits(b))) @vprintln :PolyFactor 1 "using a precision of $N" - setprecision!(C, N) + S, M, pM = with_precision(C, N) do + vH = vanHoeijCtx() + if degree(P) == 1 + vH.H = HenselCtxPadic(map_coefficients(x->coeff(mC(x), 0), f, cached = false)) + else + vH.H = HenselCtxQadic(map_coefficients(mC, f, cached = false)) + end + vH.C = C + vH.P = P - vH = vanHoeijCtx() - if degree(P) == 1 - vH.H = HenselCtxPadic(map_coefficients(x->coeff(mC(x), 0), f, cached = false)) - else - vH.H = HenselCtxQadic(map_coefficients(mC, f, cached = false)) - end - vH.C = C - vH.P = P + @vtime :PolyFactor 1 grow_prec!(vH, N) - @vtime :PolyFactor 1 grow_prec!(vH, N) + H = vH.H - H = vH.H + M = vH.Ml + pM = vH.pMr - M = vH.Ml - pM = vH.pMr + lf = factor(H) - lf = factor(H) - zk = order(P) + if degree(P) == 1 + S = Set(map(x -> map_coefficients(y -> lift(ZZ, y), x, parent = parent(f)), lf)) + else + S = Set(map(x -> map_coefficients(y -> preimage(mC, y), x, parent = parent(f)), lf)) + end + return S, M, pM + end # with_precision C - if degree(P) == 1 - S = Set(map(x -> map_coefficients(y -> lift(ZZ, y), x, parent = parent(f)), lf)) - else - S = Set(map(x -> map_coefficients(y -> preimage(mC, y), x, parent = parent(f)), lf)) - end + zk = order(P) #TODO: test reco result for being small, do early abort #TODO: test selected coefficients first without computing the product #TODO: once a factor is found (need to enumerate by size!!!), remove stuff... @@ -561,14 +569,14 @@ function van_hoeij(f::PolyRingElem{AbsSimpleNumFieldElem}, P::AbsNumFieldOrderId N = degree(f) @vprintln :PolyFactor 1 "Having $r local factors for degree $N" - setprecision!(C, 5) - vH = vanHoeijCtx() - if degree(P) == 1 - vH.H = HenselCtxPadic(map_coefficients(x->coeff(mC(x), 0), f, cached = false)) - else - vH.H = HenselCtxQadic(map_coefficients(mC, f, cached = false)) - end + with_precision(C, 5) do + if degree(P) == 1 + vH.H = HenselCtxPadic(map_coefficients(x->coeff(mC(x), 0), f, cached = false)) + else + vH.H = HenselCtxQadic(map_coefficients(mC, f, cached = false)) + end + end # with_precision C vH.C = C vH.P = P @@ -619,16 +627,16 @@ function van_hoeij(f::PolyRingElem{AbsSimpleNumFieldElem}, P::AbsNumFieldOrderId else i= sort(b)[div(length(b)+1, 2)] end - i = max(i, kk) #this seems to suggest, that prec is large enough to find factors! So the fail-2 works - @vprintln :PolyFactor 1 "setting prec to $i, and lifting the info ..." - setprecision!(codomain(mC), i) - if degree(P) == 1 - vH.H.f = map_coefficients(x->coeff(mC(x), 0), f, cached = false) - else - vH.H.f = map_coefficients(mC, f, cached = false) - end - @vtime :PolyFactor 1 grow_prec!(vH, i) - + working_prec = max(i, kk) #this seems to suggest, that prec is large enough to find factors! So the fail-2 works + @vprintln :PolyFactor 1 "setting prec to $working_prec, and lifting the info ..." + with_precision(codomain(mC), working_prec) do + if degree(P) == 1 + vH.H.f = map_coefficients(x->coeff(mC(x), 0), f, cached = false) + else + vH.H.f = map_coefficients(mC, f, cached = false) + end + @vtime :PolyFactor 1 grow_prec!(vH, i) + end # with_precision codomain(mC) av_bits = sum(nbits, vH.Ml)/degree(K)^2 #Ml: lll basis of P^i? @vprintln :PolyFactor 1 "obtaining CLDs..." @@ -643,12 +651,15 @@ function van_hoeij(f::PolyRingElem{AbsSimpleNumFieldElem}, P::AbsNumFieldOrderId b = b[vcat(1:up_to, length(b)-(N-from-1):length(b))] have = vcat(0:up_to-1, from:N-2) #N-1 is always 1 - if degree(P) == 1 - mD = MapFromFunc(K, base_ring(vH.H.f), x->coeff(mC(x),0), y->K(lift(ZZ, y))) - @vtime :PolyFactor 1 C = cld_data(vH.H, up_to, from, mD, vH.pM[1], den*leading_coefficient(f)) - else - @vtime :PolyFactor 1 C = cld_data(vH.H, up_to, from, mC, vH.pM[1], den*leading_coefficient(f)) - end + C = with_precision(codomain(mC), working_prec) do + if degree(P) == 1 + mD = MapFromFunc(K, base_ring(vH.H.f), x->coeff(mC(x),0), y->K(lift(ZZ, y))) + @vtime :PolyFactor 1 C = cld_data(vH.H, up_to, from, mD, vH.pM[1], den*leading_coefficient(f)) + else + @vtime :PolyFactor 1 C = cld_data(vH.H, up_to, from, mC, vH.pM[1], den*leading_coefficient(f)) + end + return C + end # with_precision codomain(mC) # In the end, p-adic precision needs to be large enough to # cover some CLDs. If you want the factors, it also has to @@ -717,7 +728,7 @@ function van_hoeij(f::PolyRingElem{AbsSimpleNumFieldElem}, P::AbsNumFieldOrderId i = findfirst(x->x == n, have) #new data will be in block i of C @vprintln :PolyFactor 2 "trying to use coeff $n which is $i" - if b[i] > precision(codomain(mC)) + if b[i] > working_prec @vprintln :PolyFactor 2 "not enough precision for CLD $i, $b, $(precision(codomain(mC))), skipping" # error() @@ -781,12 +792,15 @@ function van_hoeij(f::PolyRingElem{AbsSimpleNumFieldElem}, P::AbsNumFieldOrderId for v = values(d) #trivial test: if isone(den) && is_monic(f) #don't know what to do for non-monics - a = prod(map(constant_coefficient, factor(vH.H)[v])) - if degree(P) == 1 - A = K(reco(order(P)(lift(ZZ, a)), vH.Ml, vH.pMr)) - else - A = K(reco(order(P)(preimage(mC, a)), vH.Ml, vH.pMr)) - end + A = with_precision(codomain(mC), working_prec) do + a = prod(map(constant_coefficient, factor(vH.H)[v])) + if degree(P) == 1 + A = K(reco(order(P)(lift(ZZ, a)), vH.Ml, vH.pMr)) + else + A = K(reco(order(P)(preimage(mC, a)), vH.Ml, vH.pMr)) + end + return A + end # with_precision codomain(mC) if denominator(divexact(constant_coefficient(f), A), order(P)) != 1 @vprintln :PolyFactor 2 "Fail: const coeffs do not divide" push!(fail, v) @@ -796,12 +810,15 @@ function van_hoeij(f::PolyRingElem{AbsSimpleNumFieldElem}, P::AbsNumFieldOrderId continue end end - @vtime :PolyFactor 2 g = prod(factor(vH.H)[v]) - if degree(P) == 1 - @vtime :PolyFactor 2 G = parent(f)([K(reco(lift(ZZ, coeff(mC(den*leading_coefficient(f)), 0)*coeff(g, l)), vH.Ml, vH.pMr, order(P))) for l=0:degree(g)]) - else - @vtime :PolyFactor 2 G = parent(f)([K(reco(order(P)(preimage(mC, mC(den*leading_coefficient(f))*coeff(g, l))), vH.Ml, vH.pMr)) for l=0:degree(g)]) - end + G = with_precision(codomain(mC), working_prec) do + @vtime :PolyFactor 2 g = prod(factor(vH.H)[v]) + if degree(P) == 1 + @vtime :PolyFactor 2 G = parent(f)([K(reco(lift(ZZ, coeff(mC(den*leading_coefficient(f)), 0)*coeff(g, l)), vH.Ml, vH.pMr, order(P))) for l=0:degree(g)]) + else + @vtime :PolyFactor 2 G = parent(f)([K(reco(order(P)(preimage(mC, mC(den*leading_coefficient(f))*coeff(g, l))), vH.Ml, vH.pMr)) for l=0:degree(g)]) + end + return G + end # with_precision codomain(mC) G *= 1//(den*leading_coefficient(f)) if !iszero(rem(f, G)) diff --git a/test/LocalField/LocalField.jl b/test/LocalField/LocalField.jl index 0bfb88954d..0404ff7170 100644 --- a/test/LocalField/LocalField.jl +++ b/test/LocalField/LocalField.jl @@ -203,7 +203,7 @@ Qp = padic_field(2, precision = 100) Qpx, x = polynomial_ring(Qp) K, a = unramified_extension(x^2+x+1) - Qq, gQq = qadic_field(2, 2, precision = 100) + Qq, gQq = unramified_extension(Qp, 2, precision = 100) rt = roots(map_coefficients(Qq, defining_polynomial(K))) f = @inferred hom(K, Qq, rt[1])