diff --git a/docs/src/quad_forms/basics.md b/docs/src/quad_forms/basics.md index e8e3a6967a..4cd5cef002 100644 --- a/docs/src/quad_forms/basics.md +++ b/docs/src/quad_forms/basics.md @@ -115,6 +115,7 @@ gram_matrix(::AbstractSpace{T}, ::Vector{Vector{U}}) where {T, U} inner_product(::AbstractSpace, ::Vector, ::Vector) orthogonal_basis(::AbstractSpace) diagonal(::AbstractSpace) +diagonal_with_transform(::AbstractSpace) restrict_scalars(::AbstractSpace, ::QQField, ::FieldElem) ``` diff --git a/src/QuadForm/Herm/Spaces.jl b/src/QuadForm/Herm/Spaces.jl index ed22debd17..0eb6ce9216 100644 --- a/src/QuadForm/Herm/Spaces.jl +++ b/src/QuadForm/Herm/Spaces.jl @@ -148,14 +148,22 @@ inner_product(V::HermSpace{S,T,U,W}, v::U, w::U) where {S,T,U,W}= v*gram_matrix( # ################################################################################ -function diagonal(V::HermSpace) +diagonal(V::HermSpace) = _diagonal(V, false)[1] + +diagonal_with_transform(V::HermSpace) = _diagonal(V) + +function _diagonal(V::HermSpace, with_transform::Bool = true) + E = base_ring(V) g = gram_matrix(V) k, K = left_kernel(g) B = complete_to_basis(K) g = B[k+1:end,:]*g*transpose(B[k+1:end,:]) - D, _ = _gram_schmidt(g, involution(V)) - D = append!(zeros(base_ring(V),k), diagonal(D)) - return map(fixed_field(V), D) + D, U = _gram_schmidt(g, involution(V)) + diagE = append!(zeros(base_ring(V),k), diagonal(D)) + diagK = map(fixed_field(V), diagE) + !with_transform && return diagK, matrix(E, 0, 0, elem_type(E)[]) + B[k+1:end, :] = U*view(B, k+1:nrows(B), :) + return diagK, B end ################################################################################ diff --git a/src/QuadForm/Quad/Spaces.jl b/src/QuadForm/Quad/Spaces.jl index 625b5156ee..425e3714a9 100644 --- a/src/QuadForm/Quad/Spaces.jl +++ b/src/QuadForm/Quad/Spaces.jl @@ -190,13 +190,21 @@ end # ################################################################################ -function diagonal(V::QuadSpace) +diagonal(V::QuadSpace) = _diagonal(V, false)[1] + +diagonal_with_transform(V::QuadSpace) = _diagonal(V) + +function _diagonal(V::QuadSpace, with_transform::Bool = true) + E = base_ring(V) g = gram_matrix(V) k, K = left_kernel(g) B = complete_to_basis(K) g = B[k+1:end,:]*g*transpose(B[k+1:end,:]) - D, _ = _gram_schmidt(g, involution(V)) - return append!(zeros(base_ring(V),k),diagonal(D)) + D, U = _gram_schmidt(g, involution(V)) + diag = append!(zeros(base_ring(V), k), diagonal(D)) + !with_transform && return diag, matrix(E, 0, 0, elem_type(E)[]) + B[k+1:end, :] = U*view(B, k+1:nrows(B), :) + return diag, B end ################################################################################ diff --git a/src/QuadForm/Spaces.jl b/src/QuadForm/Spaces.jl index af272d7aba..9ae3ea5c71 100644 --- a/src/QuadForm/Spaces.jl +++ b/src/QuadForm/Spaces.jl @@ -1,7 +1,7 @@ export ambient_space, rank, gram_matrix, inner_product, involution, is_hermitian, is_quadratic, is_regular, is_local_square, is_isometric, is_rationally_isometric, is_isotropic, is_isotropic_with_vector, quadratic_space, hermitian_space, diagonal, invariants, hasse_invariant, witt_invariant, orthogonal_basis, fixed_field, - restrict_scalars, orthogonal_complement, orthogonal_projection + restrict_scalars, orthogonal_complement, orthogonal_projection, diagonal_with_transform ################################################################################ # @@ -319,6 +319,19 @@ The elements are contained in the fixed field of `V`. """ diagonal(V::AbstractSpace) +@doc raw""" + diagonal_with_transform(V::AbstractSpace) -> Vector{FieldElem}, + MatElem{FieldElem} + +Return a vector of elements $a_1,\dotsc,a_n$ such that the space `V` is +isometric to the diagonal space $\langle a_1,\dotsc,a_n \rangle$. The second +output is a matrix `U` whose rows span an orthogonal basis of `V` for which the +Gram matrix is given by the diagonal matrix of the $a_i$'s. + +The elements are contained in the fixed field of `V`. +""" +diagonal_with_transform(V::AbstractSpace) + ################################################################################ # # Gram-Schmidt diff --git a/test/QuadForm/Herm/Spaces.jl b/test/QuadForm/Herm/Spaces.jl index f5d3c1f5e9..8006038960 100644 --- a/test/QuadForm/Herm/Spaces.jl +++ b/test/QuadForm/Herm/Spaces.jl @@ -130,3 +130,12 @@ @test is_isometric(V1, V2) end + +@testset "diagonal with transform" begin + E, b = cyclotomic_field_as_cm_extension(3) + K = base_field(E) + s = involution(E) + Vh = hermitian_space(E, E[1 b 1; s(b) 4 s(b); 1 b 1]) + diag, U = @inferred diagonal_with_transform(Vh) + @test diagonal(map_entries(K, U*gram_matrix(Vh)*map_entries(s, transpose(U)))) == diag +end diff --git a/test/QuadForm/Quad/Spaces.jl b/test/QuadForm/Quad/Spaces.jl index 340ea549d2..38f46a83c7 100644 --- a/test/QuadForm/Quad/Spaces.jl +++ b/test/QuadForm/Quad/Spaces.jl @@ -524,3 +524,10 @@ end @test !is_isotropic(V, 5) @test_throws ArgumentError is_isotropic(V, 4) end + +@testset "diagonal with transform" begin + K, a = cyclotomic_field(8) + V = quadratic_space(K, K[a 3 a; 3 3 3; a 3 a]) + diag, U = @inferred diagonal_with_transform(V) + @test diagonal(U*gram_matrix(V)*transpose(U)) == diag +end