From d7353e0ae495332e9b9231f65dc015111fe02a84 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Wed, 11 Sep 2024 12:15:53 +0200 Subject: [PATCH 1/3] next iteration - install `GapObj` and `GAP.julia_to_gap` methods via `GAP.@install` - change the `GAP.julia_to_gap` calls to `GapObj` calls - move some conversion methods from Oscar.jl to GAP.jl --- examples/CatSLP.jl | 2 +- gap/OscarInterface/gap/alnuth.gi | 4 +- src/GAP/iso_oscar_gap.jl | 4 +- src/GAP/oscar_to_gap.jl | 63 ++++++-------------------------- src/GAP/wrappers.jl | 1 + src/Groups/GAPGroups.jl | 2 +- src/Groups/cosets.jl | 6 +-- src/Groups/group_characters.jl | 2 +- src/Groups/matrices/MatGrp.jl | 4 +- src/Groups/matrices/forms.jl | 2 +- src/Groups/tom.jl | 6 +-- src/Groups/types.jl | 6 +-- test/GAP/oscar_to_gap.jl | 24 ++++++------ 13 files changed, 42 insertions(+), 84 deletions(-) diff --git a/examples/CatSLP.jl b/examples/CatSLP.jl index 2b3ffb032acb..9bcefcd2b54e 100644 --- a/examples/CatSLP.jl +++ b/examples/CatSLP.jl @@ -26,7 +26,7 @@ function tolazy(x, dict=IdDict{Any,Lazy}()) arguments = GenesisOfCellArguments(x) argumentslazy = (tolazy(arguments[i], dict) for i in 1:length(arguments)) call(argumentslazy...) do args... - operation(map(arg -> arg isa Vector ? julia_to_gap(arg) : arg, args)...) + operation(map(arg -> arg isa Vector ? GapObj(arg) : arg, args)...) end else Lazy(x) diff --git a/gap/OscarInterface/gap/alnuth.gi b/gap/OscarInterface/gap/alnuth.gi index 05bc941d08c5..218e50095460 100644 --- a/gap/OscarInterface/gap/alnuth.gi +++ b/gap/OscarInterface/gap/alnuth.gi @@ -56,12 +56,12 @@ BindGlobal("ExponentsOfUnitsDescriptionWithRankOscar", function(F, elms) units := JuliaToGAP(IsList, basis, true); # the order of the torsion part of the full unit group - rank := Oscar.GAP.julia_to_gap(Oscar.order(U_m[1][1])); + rank := Oscar.GAP.GapObj(Oscar.order(U_m[1][1])); expns := []; for x in elms do # map GAP int vector to Oscar element - Add(expns, Oscar.GAP.julia_to_gap(Oscar.preimage(m, K(GAPToJulia(x))).coeff)[1]); + Add(expns, Oscar.GAP.GapObj(Oscar.preimage(m, K(GAPToJulia(x))).coeff)[1]); od; # return result diff --git a/src/GAP/iso_oscar_gap.jl b/src/GAP/iso_oscar_gap.jl index fecdee0bd862..deba503bd14a 100644 --- a/src/GAP/iso_oscar_gap.jl +++ b/src/GAP/iso_oscar_gap.jl @@ -64,7 +64,7 @@ function _make_prime_field_functions(FO, FG) e = GAPWrap.One(FG) f = function(x) - y = GAP.julia_to_gap(_ffe_to_int(x))::GapInt + y = GapObj(_ffe_to_int(x))::GapInt return y*e end @@ -391,7 +391,7 @@ end # Assume that `FO` is a `QQAbField` and `FG` is `GAP.Globals.Cyclotomics`. function _iso_oscar_gap_abelian_closure_functions(FO::QQAbField, FG::GapObj) - return (GAP.julia_to_gap, QQAbFieldElem) + return (GapObj, QQAbFieldElem) end function _iso_oscar_gap(FO::QQAbField) diff --git a/src/GAP/oscar_to_gap.jl b/src/GAP/oscar_to_gap.jl index 880a42293e6a..423e2e4467a0 100644 --- a/src/GAP/oscar_to_gap.jl +++ b/src/GAP/oscar_to_gap.jl @@ -3,8 +3,8 @@ ## where low level Julia objects are treated) ## `ZZRingElem` to GAP integer -function GAP.julia_to_gap(obj::ZZRingElem) - Nemo._fmpz_is_small(obj) && return GAP.julia_to_gap(Int(obj)) +GAP.@install function GapObj(obj::ZZRingElem) + Nemo._fmpz_is_small(obj) && return GapObj(Int(obj)) GC.@preserve obj begin x = Nemo._as_bigint(obj) return ccall((:MakeObjInt, GAP.libgap), GapObj, (Ptr{UInt64}, Cint), x.d, x.size) @@ -12,77 +12,38 @@ function GAP.julia_to_gap(obj::ZZRingElem) end ## `QQFieldElem` to GAP rational -GAP.julia_to_gap(obj::QQFieldElem) = GAP.Globals.QUO(GAP.julia_to_gap(numerator(obj)), GAP.julia_to_gap(denominator(obj))) +GAP.@install GapObj(obj::QQFieldElem) = GAPWrap.QUO(GapObj(numerator(obj)), GapObj(denominator(obj))) ## `PosInf` to GAP infinity -GAP.julia_to_gap(obj::PosInf) = GAP.Globals.infinity +GAP.@install GapObj(obj::PosInf) = GAP.Globals.infinity ## `ZZMatrix` to matrix of GAP integers -GAP.julia_to_gap(obj::ZZMatrix) = GAP.julia_to_gap(Matrix(obj); recursive = true) +GAP.@install GapObj(obj::ZZMatrix) = GAP.GapObj(Matrix(obj); recursive = true) ## `QQMatrix` to matrix of GAP rationals or integers -GAP.julia_to_gap(obj::QQMatrix) = GAP.julia_to_gap(Matrix(obj); recursive = true) +GAP.@install GapObj(obj::QQMatrix) = GAP.GapObj(Matrix(obj); recursive = true) ## element of cyclotomic field to GAP cyclotomic -function GAP.julia_to_gap(obj::AbsSimpleNumFieldElem) +GAP.@install function GapObj(obj::AbsSimpleNumFieldElem) F = parent(obj) @req Nemo.is_cyclo_type(F) "the element does not lie in a cyclotomic field" N = get_attribute(F, :cyclo) v = zeros(QQFieldElem, N) coeffs = coefficients(obj) v[1:length(coeffs)] = coeffs - return GAPWrap.CycList(GAP.julia_to_gap(v; recursive = true)) + return GAPWrap.CycList(GapObj(v; recursive = true)) end ## `QQAbFieldElem` to GAP cyclotomic -function GAP.julia_to_gap(elm::QQAbFieldElem) +GAP.@install function GapObj(elm::QQAbFieldElem) coeffs = [Nemo.coeff(elm.data, i) for i in 0:(elm.c-1)] # QQFieldElem return GAPWrap.CycList(GapObj(coeffs; recursive = true)) end ## matrix of elements of cyclotomic field to GAP matrix of cyclotomics -function GAP.julia_to_gap(obj::AbstractAlgebra.Generic.MatSpaceElem{AbsSimpleNumFieldElem}) +GAP.@install function GapObj(obj::AbstractAlgebra.Generic.MatSpaceElem{AbsSimpleNumFieldElem}) F = base_ring(obj) @req Nemo.is_cyclo_type(F) "the matrix entries do not lie in a cyclotomic field" - mat = [GAP.julia_to_gap(obj[i,j]) for i in 1:nrows(obj), j in 1:ncols(obj)] - return GAP.julia_to_gap(mat) -end - -## TODO: remove the following once GAP.jl has it -function GAP.julia_to_gap( - obj::Set{T}, - recursion_dict::IdDict{Any,Any} = IdDict(); - recursive::Bool = false, -) where {T} - - gapset = GAP.NewPlist(length(obj)) - if recursive - recursion_dict[obj] = gapset - end - for x in obj - if recursive - x = get!(recursion_dict, x) do - GAP.julia_to_gap(x, recursion_dict; recursive) - end - end - GAP.Globals.Add(gapset, x) - end - GAP.Globals.Sort(gapset) - @assert GAPWrap.IsSet(gapset) - - return gapset -end - -## TODO: remove the following once GAP.jl has it -## (This will be the case when the change from -## https://github.com/oscar-system/GAP.jl/pull/989 -## will be available.) -using JSON3 - -function GAP.julia_to_gap( - obj::JSON3.Array, - recursion_dict::IdDict{Any,Any} = IdDict(); - recursive::Bool = false) - - return GAP.julia_to_gap(copy(obj), recursion_dict; recursive) + mat = [GapObj(obj[i,j]) for i in 1:nrows(obj), j in 1:ncols(obj)] + return GapObj(mat) end diff --git a/src/GAP/wrappers.jl b/src/GAP/wrappers.jl index f4e3093013f2..d248a4572fd5 100644 --- a/src/GAP/wrappers.jl +++ b/src/GAP/wrappers.jl @@ -315,6 +315,7 @@ GAP.@wrap PrimePGroup(x::GapObj)::GapInt GAP.@wrap PrimitiveElement(x::GapObj)::GapObj GAP.@wrap Projection(x::GapObj)::GapObj GAP.@wrap Projection(x::GapObj, i::Int)::GapObj +GAP.@wrap QUO(x::GAP.Obj, y::GAP.Obj)::GAP.Obj GAP.@wrap Random(x::GapObj, y::GapObj)::GAP.Obj GAP.@wrap Range(x::GapObj)::GapObj GAP.@wrap RecognizeGroup(x::GapObj)::GapObj diff --git a/src/Groups/GAPGroups.jl b/src/Groups/GAPGroups.jl index 943369674650..b71cbaf8509a 100644 --- a/src/Groups/GAPGroups.jl +++ b/src/Groups/GAPGroups.jl @@ -695,7 +695,7 @@ end end end -GAP.julia_to_gap(obj::GAPGroupConjClass) = obj.CC +GAP.@install GapObj(obj::GAPGroupConjClass) = obj.CC Base.eltype(::Type{GAPGroupConjClass{T,S}}) where {T,S} = S diff --git a/src/Groups/cosets.jl b/src/Groups/cosets.jl index b5de363e8aa0..9fc72c240dc3 100644 --- a/src/Groups/cosets.jl +++ b/src/Groups/cosets.jl @@ -14,7 +14,7 @@ struct GroupCoset{T<: GAPGroup, S <: GAPGroupElem} X::GapObj # GapObj(H*repr) end -GAP.julia_to_gap(obj::GroupCoset) = obj.X +GAP.@install GapObj(obj::GroupCoset) = obj.X Base.hash(x::GroupCoset, h::UInt) = h # FIXME Base.eltype(::Type{GroupCoset{T,S}}) where {T,S} = S @@ -317,7 +317,7 @@ struct SubgroupTransversal{T<: GAPGroup, S<: GAPGroup, E<: GAPGroupElem} <: Abst X::GapObj # underlying *right* transversal in GAP end -GAP.julia_to_gap(T::SubgroupTransversal, d::IdDict{Any,Any} = IdDict(); recursive::Bool = false) = T.X +GAP.@install GapObj(T::SubgroupTransversal) = T.X function Base.show(io::IO, ::MIME"text/plain", x::SubgroupTransversal) side = x.side === :left ? "Left" : "Right" @@ -473,7 +473,7 @@ struct GroupDoubleCoset{T <: GAPGroup, S <: GAPGroupElem} end end -function GAP.julia_to_gap(C::GroupDoubleCoset) +GAP.@install function GapObj(C::GroupDoubleCoset) if !isassigned(C.X) C.X[] = GAPWrap.DoubleCoset(GapObj(C.H), GapObj(representative(C)), GapObj(C.K)) end diff --git a/src/Groups/group_characters.jl b/src/Groups/group_characters.jl index d5d311524eb0..d921b59c422c 100644 --- a/src/Groups/group_characters.jl +++ b/src/Groups/group_characters.jl @@ -1899,7 +1899,7 @@ GapObj(chi::GAPGroupClassFunction) = chi.values # The following is needed for recursive `GapObj` calls with arrays # of class functions. -GAP.julia_to_gap(chi::GAPGroupClassFunction) = chi.values +GAP.@install GapObj(chi::GAPGroupClassFunction) = chi.values parent(chi::GAPGroupClassFunction) = chi.table diff --git a/src/Groups/matrices/MatGrp.jl b/src/Groups/matrices/MatGrp.jl index f6b24eba351e..0c954d4030ee 100644 --- a/src/Groups/matrices/MatGrp.jl +++ b/src/Groups/matrices/MatGrp.jl @@ -219,7 +219,7 @@ function _ring_iso(G::MatrixGroup{T}) where T return G.ring_iso end -function GAP.julia_to_gap(G::MatrixGroup) +GAP.@install function GapObj(G::MatrixGroup) if !isdefined(G, :X) if isdefined(G, :descr) assign_from_description(G) @@ -233,7 +233,7 @@ function GAP.julia_to_gap(G::MatrixGroup) return G.X end -function GAP.julia_to_gap(x::MatrixGroupElem) +GAP.@install function GapObj(x::MatrixGroupElem) if !isdefined(x, :X) x.X = map_entries(_ring_iso(x.parent), x.elm) end diff --git a/src/Groups/matrices/forms.jl b/src/Groups/matrices/forms.jl index 0f7f708ec25f..887df1bbbb42 100644 --- a/src/Groups/matrices/forms.jl +++ b/src/Groups/matrices/forms.jl @@ -304,7 +304,7 @@ function _ring_iso(f::SesquilinearForm) return f.ring_iso end -function GAP.julia_to_gap(f::SesquilinearForm) +GAP.@install function GapObj(f::SesquilinearForm) if !isdefined(f, :X) assign_from_description(f) end diff --git a/src/Groups/tom.jl b/src/Groups/tom.jl index bae14a09b406..de7356088981 100644 --- a/src/Groups/tom.jl +++ b/src/Groups/tom.jl @@ -474,11 +474,7 @@ struct GAPGroupMarksVector <: GroupMarksVector values::GapObj end -GapObj(chi::GAPGroupMarksVector) = chi.values - -# The following is needed for recursive `GapObj` calls with arrays -# of marks vectors. -GAP.julia_to_gap(chi::GAPGroupMarksVector) = GapObj(chi) +GAP.@install GapObj(chi::GAPGroupMarksVector) = chi.values parent(chi::GAPGroupMarksVector) = chi.table diff --git a/src/Groups/types.jl b/src/Groups/types.jl index 7e985e4c2032..b1c773c3d3b5 100644 --- a/src/Groups/types.jl +++ b/src/Groups/types.jl @@ -13,8 +13,8 @@ Concrete subtypes of `GAPGroup` are `PermGroup`, `FPGroup`, `SubFPGroup`, """ abstract type GAPGroup <: AbstractAlgebra.Group end -## `GapGroup` to GAP group -GAP.julia_to_gap(obj::GAPGroup) = obj.X +## `GapGroup` to underlying GAP group +GAP.@install GapObj(obj::GAPGroup) = obj.X @doc raw""" GAPGroupElem <: AbstractAlgebra.GroupElem @@ -29,7 +29,7 @@ i.e., if `g` is a `GAPGroupElem`, then `GapObj(g)` is the `GapObj` underlying `g abstract type GAPGroupElem{T<:GAPGroup} <: AbstractAlgebra.GroupElem end ## `GapGroupElem` to GAP group element -GAP.julia_to_gap(obj::GAPGroupElem) = obj.X +GAP.@install GapObj(obj::GAPGroupElem) = obj.X @doc raw""" BasicGAPGroupElem{T<:GAPGroup} <: GAPGroupElem{T} diff --git a/test/GAP/oscar_to_gap.jl b/test/GAP/oscar_to_gap.jl index c6ede37f9e26..86792b84e137 100644 --- a/test/GAP/oscar_to_gap.jl +++ b/test/GAP/oscar_to_gap.jl @@ -2,13 +2,13 @@ # small (GAP) integer x = ZZRingElem(17) val = 17 - @test GAP.julia_to_gap(x) == val + @test GapObj(x) == val @test GAP.Obj(x) == val # large GAP integer x = ZZRingElem(2)^65 val = GAP.evalstr("2^65") - @test GAP.julia_to_gap(x) == val + @test GapObj(x) == val @test GAP.Obj(x) == val end @@ -16,25 +16,25 @@ end # small (GAP) integer x = ZZRingElem(17) val = 17 - @test GAP.julia_to_gap(x) == val + @test GapObj(x) == val @test GAP.Obj(x) == val # large GAP integer x = ZZRingElem(2)^65 val = GAP.evalstr("2^65") - @test GAP.julia_to_gap(x) == val + @test GapObj(x) == val @test GAP.Obj(x) == val # non-integer rational, small numerator and denominator x = QQFieldElem(2, 3) val = GAP.evalstr("2/3") - @test GAP.julia_to_gap(x) == val + @test GapObj(x) == val @test GAP.Obj(x) == val # non-integer rational, large numerator and denominator x = QQFieldElem(ZZRingElem(2)^65, ZZRingElem(3)^40) val = GAP.evalstr("2^65/3^40") - @test GAP.julia_to_gap(x) == val + @test GapObj(x) == val @test GAP.Obj(x) == val end @@ -42,13 +42,13 @@ end # matrix of small (GAP) integers x = Nemo.ZZ[1 2; 3 4] val = GAP.evalstr( "[ [ 1, 2 ], [ 3, 4 ] ]" ) - @test GAP.julia_to_gap(x) == val + @test GapObj(x) == val @test GAP.Obj(x) == val # matrix containing small and large integers x = Nemo.ZZ[1 BigInt(2)^65; 3 4] val = GAP.evalstr( "[ [ 1, 2^65 ], [ 3, 4 ] ]" ) - @test GAP.julia_to_gap(x) == val + @test GapObj(x) == val @test GAP.Obj(x) == val end @@ -56,25 +56,25 @@ end # matrix of small (GAP) integers x = Nemo.QQ[1 2; 3 4] val = GAP.evalstr( "[ [ 1, 2 ], [ 3, 4 ] ]" ) - @test GAP.julia_to_gap(x) == val + @test GapObj(x) == val @test GAP.Obj(x) == val # matrix containing small and large integers x = Nemo.QQ[1 BigInt(2)^65; 3 4] val = GAP.evalstr( "[ [ 1, 2^65 ], [ 3, 4 ] ]" ) - @test GAP.julia_to_gap(x) == val + @test GapObj(x) == val @test GAP.Obj(x) == val # matrix containing non-integer rationals, small numerator and denominator x = Nemo.QQ[QQFieldElem(1, 2) 2; 3 4] val = GAP.evalstr( "[ [ 1/2, 2 ], [ 3, 4 ] ]" ) - @test GAP.julia_to_gap(x) == val + @test GapObj(x) == val @test GAP.Obj(x) == val # matrix containing non-integer rationals, large numerator and denominator x = Nemo.QQ[QQFieldElem(ZZRingElem(2)^65, ZZRingElem(3)^40) 2; 3 4] val = GAP.evalstr( "[ [ 2^65/3^40, 2 ], [ 3, 4 ] ]" ) - @test GAP.julia_to_gap(x) == val + @test GapObj(x) == val @test GAP.Obj(x) == val end From 240c3b42db6e9e0a8be8cbc94e323f0e1a7e674e Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Fri, 20 Sep 2024 12:30:38 +0200 Subject: [PATCH 2/3] do not call `GapObj(Union{}[])` --- src/Serialization/GAP.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Serialization/GAP.jl b/src/Serialization/GAP.jl index 26908eb23103..631ede44744c 100644 --- a/src/Serialization/GAP.jl +++ b/src/Serialization/GAP.jl @@ -143,7 +143,12 @@ install_GAP_deserialization( GapObj(nameprefix) end init = load_node(s, :names) do names - GapObj(names; recursive = true) + if length(names) == 0 + GapObj([]) + else + # problem with `Union{}[]` + GapObj(names; recursive = true) + end end G = GAP.Globals.FreeGroup(wfilt, GAP.Globals.infinity, prefix, init)::GapObj else From f9e4450aada57866f9f571323188c27b6e555476 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Tue, 24 Sep 2024 12:22:42 +0200 Subject: [PATCH 3/3] require GAP.jl 0.12 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index f58c37819f69..27fb7432fb23 100644 --- a/Project.toml +++ b/Project.toml @@ -28,7 +28,7 @@ cohomCalg_jll = "5558cf25-a90e-53b0-b813-cadaa3ae7ade" AbstractAlgebra = "0.43.1" AlgebraicSolving = "0.7.0" Distributed = "1.6" -GAP = "0.11.3" +GAP = "0.12.0" Hecke = "0.34.3" JSON = "^0.20, ^0.21" JSON3 = "1.13.2"