Skip to content

Commit

Permalink
Add comments on the implementation of local Hilbert symbols (#1328)
Browse files Browse the repository at this point in the history
  • Loading branch information
StevellM authored Dec 23, 2023
1 parent cf581d0 commit d15f5e2
Showing 1 changed file with 90 additions and 5 deletions.
95 changes: 90 additions & 5 deletions src/NumField/Hilbert.jl
Original file line number Diff line number Diff line change
Expand Up @@ -160,20 +160,41 @@ function hilbert_symbol(a::IntegerUnion, b::NumFieldElem, p::Union{NfAbsOrdIdl,
return hilbert_symbol(b, a, p)
end

# This is an implementation of local Hilbert symbol computations by M. Kirschmer
# using quadratic defects.
#
# References:
# [O'M71] O. T. O'Meara, "Introduction to quadratic forms", volume 117 of
# Grundlehren der Mathematischen Weissenschaften, 1971.
#
# [Voi12] J. Voight, "IDENTIFYING THE MATRIX RING: ALGORITHMS FOR QUATERNION
# ALGEBRAS AND QUADRATIC FORMS", In Quadratic and higher degree
# forms, volume 31 of Dev. Math., pages 255-298, 2012.
@doc raw"""
hilbert_symbol(a::NumFieldElem, b::NumFieldElem, p::NfOrdIdl) -> Int
Returns the local Hilbert symbol $(a,b)_p$.
"""
function hilbert_symbol(a::T, b::T, p::Union{NfAbsOrdIdl, NfRelOrdIdl}) where {T <: NumFieldElem}
(iszero(a) || iszero(b)) && error("arguments must be non-zero")
@req !iszero(a) && !iszero(b) "Arguments must be non-zero"
o = order(p)
f = nf(o)
f !== parent(a) && error("Incompatible parents")
@req f === parent(a) "Incompatible parents"
pi = f(uniformizer(p))

v = valuation(a,p)
w = valuation(b,p)

# We want to put ourselves in the case where a is a local unit and b
# has p-valuation 0 or 1.
#
# If a has even p-valuation and b has odd p-valuation, we exchange
# a and b. If both have odd p-valuations, then we replace a by -ab
# since
#
# (-ab, b)_p = (a,b)_p * (-1,b)_p = (a,b)_p
#
# and in that case the new a has even p-valuation
if isodd(v)
if iseven(w)
a,b,v,w = b,a,w,v
Expand All @@ -183,18 +204,60 @@ function hilbert_symbol(a::T, b::T, p::Union{NfAbsOrdIdl, NfRelOrdIdl}) where {T
end
end

# now v is even, make a a local unit
# Now v is even, so we can turn a into a local unit
a = a // pi^v

# If p is not dyadic, according to [Voi12, Corollary 5.6], the local
# Hilbert symbol is equal to the local Legendre symbol of a at p, to the
# power w.
#
# The local Legendre symbol measures whether a is a local square modulo p:
# if the local quadratic defect of a has p-valuation greater or equal
# than 1, then the local Legendre symbol is necessarily 1, and so is (a, b)_p.
#
# So eventually, the (a, b)_p = -1 if and only if the p-valuation of
# the local quadratic defect of a is 0 AND w is odd.
if !is_dyadic(p)
return isodd(w) && iszero(quadratic_defect(a, p)) ? -1 : 1
end

# Now, if the local quadratic defect of a is even or infinite we can
# already conclude:
# - if it is infinite, then a is a local square and the local Hilbert
# symbol is 1 (because (c^2, b)_p = 1 for all b, c in o_p);
# - if it is even, then by [OM71, 63:4] a is in the square class of a local
# unit whose defect is 4*o_p. In that case, [OM71, 63:11a] tells us that
# (a, b)_p = 1 if b has even p-valuation (i.e is in the square
# class of a local unit) and -1 otherwise (when b is in the square class
# of a uniformizer at p).
#
# If the p-valuation is odd, then we replace iteratively a by an element
# which admit the same local Hilbert symbol with b, but at each iteration we
# make the p-valuation of the local defect grow: hence, either it becomes
# even at some point or diverges to infinity. We then use one of the previous
# termination conditions to conclude.

# We have that a is a local unit and p is dyadic. There are 3 possibilities:
# - v is odd and smaller than the p-valuation of 4;
# - v is the p-valuation of 4;
# - v is infinity.
#
# In all cases, the new a is such that a-1 has p-valuation v and it is
# in the same square class as the old a, so (a, b)_p is unchanged
v, a = _quadratic_defect_unit(a, p)

# We reduce the p-valuation of b to 0 or 1, depending on the parity
# of w
b = b // pi^(2*fld(w, 2)) # fld(x, y) = div(x, y, RoundDown), i.e., round towards -oo
w = mod(w, 2)
# turn b into a uniformizer

# If w = 1, then b is a local uniformizer at p. Otherwise, we use that
# v is odd to turn b into a local uniformizer. This works because
# pi^(v-1) is a square and
#
# (a, (1-a)*b)_p = (a, 1-a)_p * (a,b)_p = (a,b)_p
#
# by the properties of the Hilbert symbol.
if isfinite(v) && isodd(v)
if w == 0
b = (1-a)*b // pi^(v-1)
Expand All @@ -205,7 +268,29 @@ function hilbert_symbol(a::T, b::T, p::Union{NfAbsOrdIdl, NfRelOrdIdl}) where {T
h = extend(h, f)
end

# lift v until it becomes infinite or even
# From now on, we lift v until it becomes infinite or even. How it works:
#
# Since a-1 lives locally in p^v = b*p^(v-1), one can find a local unit
# c such that a = 1 + c*b*pi^(v-1). Now, the residue field k is perfect, so
# c = (a-1)/(b*pi^(v-1)) is a square s^2 modulo p, where s is a unit in o_p.
# The important point here is the following. Since v-1 is even, s^2*pi^(v-1)
# is a local square and
#
# (a*(1-s^2*b*pi^(v-1)), b)_p = (a, b)_p * (1-s^2*b*pi^(v-1), s^2*b*pi^(v-1))_p
# = (a, b)_p
#
# and moreover
#
# a - a*s^2*b*pi^(v-1) = 1 + (c-s^2)*b*pi^(v-1) = 1 modulo p^(v+1)
#
# because b is a local uniformizer and c = s^2 modulo p.
#
# Hence, by changing a -> a * (1-s^2*b*pi^(v-1)), we have that
# a-1 has p-valuation at least v+1 and (a, b)_p remains unchanged.
#
# We then proceed iteratively by computing the local quadratic defect of
# the new a, and by replacing a by an element in its square which is one
# modulo the defect.
while isfinite(v) && isodd(v)
t = pi^(v-1)*b
ok, s = is_square_with_sqrt( h( (a-1) // t) )
Expand Down

0 comments on commit d15f5e2

Please sign in to comment.