Skip to content

Commit

Permalink
Fix _order(::NumField, ::Vector{NumFieldElem})
Browse files Browse the repository at this point in the history
  • Loading branch information
joschmitt committed Oct 9, 2023
1 parent 48c9923 commit 401a711
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 75 deletions.
121 changes: 49 additions & 72 deletions src/NumFieldOrd/NfOrd/NfOrd.jl
Original file line number Diff line number Diff line change
Expand Up @@ -993,114 +993,91 @@ The equation order of the number field.
equation_order(M::NfAbsOrd) = equation_order(nf(M))

function _order(K::S, elt::Vector{T}; cached::Bool = true, check::Bool = true, extends = nothing) where {S <: NumField{QQFieldElem}, T}
#=
check == true: the elements are known to be integral
extends !== nothing: then extends is an order, which we are extending
=#
elt = unique(elt)
n = degree(K)

extending = false

local B::FakeFmpqMat = FakeFmpqMat()

if extends !== nothing
extended_order::order_type(K) = extends
@assert K === nf(extended_order)
extending = true

if is_maximal_known_and_maximal(extended_order) || length(elt) == 0
return extended_order
end
#in this case we can start with phase 2 directly as we have mult. closed
#module to start with, so set everything up for it...
B = basis_matrix(extended_order)
bas = basis(extended_order, K)
phase = 2
full_rank = true
m = det(numerator(B, copy = false))
else
if isempty(elt)
elt = elem_type(K)[one(K)]
end
bas = elem_type(K)[one(K)]
phase = 1
B = basis_matrix(bas, FakeFmpqMat) # trivially in lower-left HNF
full_rank = false
end

for e in elt
# @show findall(isequal(e), elt)
if phase == 2
if denominator(B) % denominator(e) == 0
C = basis_matrix([e], FakeFmpqMat)
fl, _ = can_solve_with_solution(B.num, div(B.den, denominator(e))*C.num, side = :left)
# fl && println("elt known:", :e)
fl && continue
end
function in_span_of_B(x::T)
if mod(denominator(B, copy = false), denominator(x)) == 0
C = basis_matrix(elem_type(K)[x], FakeFmpqMat)
return is_zero_mod_hnf!(div(denominator(B, copy = false), denominator(x))*numerator(C, copy = false), numerator(B, copy = false))
end
return false
end

for e in elt
# Check if e is already in the multiplicative closed module generated by
# the previous elements of elt
in_span_of_B(e) && continue

# Multiply powers of e to the existing basis elements
if check
f = minpoly(e)
isone(denominator(f)) || error("data does not define an order, $e is non-integral")
df = degree(f)-1
isone(denominator(f)) || error("The elements do not define an order: $e is non-integral")
df = degree(f) - 1
else
df = n-1
df = n - 1
end
f = one(K)
for i=1:df
mul!(f, f, e)
if phase == 2 # don't understand this part
if denominator(B) % denominator(f) == 0
C = basis_matrix(elem_type(K)[f], FakeFmpqMat)
fl = is_zero_mod_hnf!(div(B.den, denominator(f))*C.num, B.num)
# fl && println("inner abort: ", :e, " ^ ", i)
fl && break
end
end
if phase == 1
# [1] -> [1, e] -> [1, e, e, e^2] -> ... otherwise
push!(bas, deepcopy(f))
else
b = elem_type(K)[e*x for x in bas]
append!(bas, b)
start = 1
for i in 1:df
new_bas = elem_type(K)[]
for j in start:length(bas)
t = e*bas[j]
in_span_of_B(t) && continue
push!(new_bas, t)
end
isempty(new_bas) && break
start = length(bas) + 1
append!(bas, new_bas)

if length(bas) >= n
# HNF reduce the basis we have so far, if B is already of full rank,
# we can do this modular
B = basis_matrix(bas, FakeFmpqMat)
if extending
# We are extending extended_order, which has basis matrix M/d
# Thus we know that B.den/d * M \subseteq <B.num>
# So we can take B.den/d * largest_elementary_divisor(M) as the modulus
B = hnf_modular_eldiv(B, B.den, shape = :lowerleft)
if full_rank
# We have M/d \subseteq B, where M/d is a former incarnation of B.
# So we can use B.den*det(M) as a modulus.
hnf_modular_eldiv!(B, denominator(B, copy = false)*m, shape = :lowerleft)
B = sub(B, nrows(B) - n + 1:nrows(B), 1:n)
else
hnf!(B)
k = findfirst(k -> !is_zero_row(B, k), nrows(B) - n + 1:nrows(B))
B = sub(B, nrows(B) - n + k:nrows(B), 1:n)
if nrows(B) == n
full_rank = true
m = det(numerator(B, copy = false))
end
end
rk = nrows(B) - n + 1
while is_zero_row(B, rk)
rk += 1
end
B = sub(B, rk:nrows(B), 1:n)
phase = 2
bas = elem_type(K)[ elem_from_mat_row(K, B.num, i, B.den) for i = 1:nrows(B) ]
bas = elem_type(K)[ elem_from_mat_row(K, numerator(B, copy = false), i, denominator(B, copy = false)) for i = 1:nrows(B) ]
start = 1
if check
@assert isone(bas[1])
end
end
end
end

if length(bas) > n # == n can only happen here after an hnf was computed
# above. Don't quite see how > n can happen here either
B = basis_matrix(bas, FakeFmpqMat)
hnf!(B)
rk = nrows(B) - n + 1
if is_zero_row(B.num, rk)
error("data does not define an order: dimension to small")
end
B = sub(B, rk:nrows(B), 1:n)
bas = elem_type(K)[ elem_from_mat_row(K, B.num, i, B.den) for i = 1:nrows(B) ]
if length(bas) < n
error("The elements do not define an order: rank too small")
end

if !isdefined(B, :num)
error("data does not define an order: dimension to small")
end

# Make an explicit check
@hassert :NfOrd 1 defines_order(K, B)[1]
return Order(K, B, cached = cached, check = check)
end

Expand Down
16 changes: 13 additions & 3 deletions test/NumFieldOrd/NumFieldOrd.jl
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,18 @@ end
@test extend(R, [1//2 + a//2]) == maximal_order(K)
@test extend(maximal_order(R), [a]) == maximal_order(R)

K, w = NumberField(x^4-10*x^2+1,"w")
a=1//2*w^3-9//2*w; b=1//2*w^3-11//2*w
Order(K,[a,b, a*b])
K, a = number_field(x, "a")
@test Order(K, [1]) == equation_order(K)
@test Order(K, []) == equation_order(K)

K, a = NumberField(x^4 - 10*x^2 + 1, "a")
x = 1//2*a^3 - 9//2*a # sqrt(2)
y = 1//2*a^3 - 11//2*a # sqrt(3)
O = Order(K, [x, y, x*y])
@test O == Order(K, [x, y])
@test O == Order(K, [x, y], check = false)
z = 1//4*a^3 + 1//4*a^2 + 3//4*a + 3//4
OO = Hecke._order(K, [z], extends = O)
@test is_maximal(OO)
end

0 comments on commit 401a711

Please sign in to comment.