diff --git a/docs/src/Groups/matgroup.md b/docs/src/Groups/matgroup.md index 17ab0aa3e385..df733faa6e50 100644 --- a/docs/src/Groups/matgroup.md +++ b/docs/src/Groups/matgroup.md @@ -11,9 +11,10 @@ end matrix_group(R::Ring, m::Int, V::AbstractVector{T}; check::Bool=true) where T<:Union{MatElem,MatrixGroupElem} MatrixGroup{RE<:RingElem, T<:MatElem{RE}} MatrixGroupElem{RE<:RingElem, T<:MatElem{RE}} -base_ring(G::MatrixGroup) +base_ring(G::MatrixGroup{RE}) where RE <: RingElem degree(G::MatrixGroup) centralizer(G::MatrixGroup{T}, x::MatrixGroupElem{T}) where T <: FinFieldElem +map_entries(f, G::MatrixGroup) ``` ## Elements of matrix groups diff --git a/src/Groups/matrices/MatGrp.jl b/src/Groups/matrices/MatGrp.jl index 3e3ed7196569..92896f6d0339 100644 --- a/src/Groups/matrices/MatGrp.jl +++ b/src/Groups/matrices/MatGrp.jl @@ -102,13 +102,7 @@ function Base.deepcopy_internal(x::MatrixGroupElem, dict::IdDict) error("$x has neither :X nor :elm") end -function change_base_ring(R::Ring, G::MatrixGroup) - g = dense_matrix_type(R)[] - for h in gens(G) - push!(g, map_entries(R, h.elm)) - end - return matrix_group(g) -end +change_base_ring(R::Ring, G::MatrixGroup) = map_entries(R, G) ######################################################################## # @@ -547,6 +541,53 @@ function order(::Type{T}, G::MatrixGroup) where T <: IntegerUnion return T(res)::T end +""" + map_entries(f, G::MatrixGroup) + +Return the matrix group obtained by applying `f` element-wise to +each generator of `G`. + +`f` can be a ring or a field, a suitable map, or a Julia function. + +# Examples +```jldoctest +julia> mat = matrix(ZZ, 2, 2, [1, 1, 0, 1]); + +julia> G = matrix_group(mat); + +julia> G2 = map_entries(x -> -x, G) +Matrix group of degree 2 + over integer ring + +julia> is_finite(G2) +false + +julia> order(map_entries(GF(3), G)) +3 +``` +""" +function map_entries(f, G::MatrixGroup) + Ggens = gens(G) + if length(Ggens) == 0 + z = f(zero(base_ring(G))) + return matrix_group(parent(z), degree(G), MatrixGroupElem[]) + else + imgs = [map_entries(f, matrix(x)) for x in gens(G)] + return matrix_group(imgs) + end +end + +function map_entries(R::Ring, G::MatrixGroup) + imgs = [map_entries(R, matrix(x)) for x in gens(G)] + return matrix_group(R, degree(G), imgs) +end + +function map_entries(mp::Map, G::MatrixGroup) + imgs = [map_entries(mp, matrix(x)) for x in gens(G)] + return matrix_group(codomain(mp), degree(G), imgs) +end + + ######################################################################## # # Constructors diff --git a/test/Groups/matrixgroups.jl b/test/Groups/matrixgroups.jl index b35b6936de9b..dbba1fd97ccf 100644 --- a/test/Groups/matrixgroups.jl +++ b/test/Groups/matrixgroups.jl @@ -379,6 +379,38 @@ end @test_throws ArgumentError matrix_group([x1,x3]) end +@testset "map_entries for matrix groups" begin + mat = matrix(ZZ, 2, 2, [1, 1, 0, 1]) + G = matrix_group(mat) + T = trivial_subgroup(G)[1] + @test length(gens(T)) == 0 + for R in [GF(2), GF(3, 2), residue_ring(ZZ, 6)[1]] + red = map_entries(R, G) + @test matrix(gen(red, 1)) == map_entries(R, mat) + red = map_entries(R, T) + @test matrix(one(red)) == map_entries(R, one(mat)) + end + + F = GF(2) + mp = MapFromFunc(ZZ, F, x -> F(x)) + red = map_entries(mp, G) + @test red == map_entries(F, G) + red = map_entries(mp, T) + @test red == map_entries(F, T) + + G1 = special_linear_group(2, 9) + G2 = map_entries(x -> x^3, G1) + @test gens(G1) != gens(G2) + @test G1 == G2 + T = trivial_subgroup(G1)[1] + @test length(gens(T)) == 0 + @test map_entries(x -> x^3, T) == trivial_subgroup(G2)[1] + + mat = matrix(QQ, 2, 2, [2, 1, 0, 1]) + G = matrix_group(mat) + @test_throws ArgumentError map_entries(GF(2), G) +end + @testset "Iterator" begin G = SL(2,3) N = 0