From ed4c9a88952ad130ac80e7d4a8d125c667d2b469 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 20 May 2026 09:13:46 +0100 Subject: [PATCH 001/114] re-edited library files, adding NC --- lib/algebra.gi | 2 +- lib/algfp.gi | 2 +- lib/alghom.gi | 16 ++--- lib/alglie.gi | 26 ++++---- lib/algrep.gi | 8 +-- lib/autsr.gi | 42 ++++++------ lib/clas.gi | 2 +- lib/clashom.gi | 48 +++++++------- lib/csetgrp.gi | 4 +- lib/ctblfuns.gi | 4 +- lib/ctblgrp.gi | 4 +- lib/ctblsolv.gi | 28 ++++---- lib/field.gi | 13 ++-- lib/fitfree.gi | 24 +++---- lib/fldabnum.gi | 12 ++-- lib/ghom.gi | 20 +++--- lib/ghomfp.gi | 16 ++--- lib/ghompcgs.gi | 8 +-- lib/ghomperm.gi | 32 +++++----- lib/gpfpiso.gi | 72 ++++++++++----------- lib/gpprmsya.gi | 2 +- lib/gprd.gi | 16 ++--- lib/gprdmat.gi | 12 ++-- lib/gprdpc.gi | 2 +- lib/gprdperm.gi | 26 ++++---- lib/grp.gi | 24 +++---- lib/grpcompl.gi | 6 +- lib/grpfp.gi | 18 +++--- lib/grplatt.gi | 6 +- lib/grpmat.gi | 10 +-- lib/grpnames.gi | 2 +- lib/grpnice.gd | 14 ++-- lib/grpnice.gi | 26 ++++---- lib/grppc.gi | 12 ++-- lib/grppcaut.gi | 20 +++--- lib/grppccom.gi | 4 +- lib/grppcext.gi | 44 ++++++------- lib/grppclat.gi | 6 +- lib/grpperm.gi | 6 +- lib/grpprmcs.gi | 16 ++--- lib/liefam.gi | 2 +- lib/mapphomo.gi | 46 +++++++------- lib/mapping.gd | 51 ++++++++++++--- lib/mapping.gi | 166 +++++++++++++++++++++++++++++++++++++++++++----- lib/mapprep.gi | 106 +++++++++++++++---------------- lib/maxsub.gi | 22 +++---- lib/mgmring.gi | 8 +-- lib/morpheus.gi | 28 ++++---- lib/norad.gi | 8 +-- lib/onecohom.gi | 10 +-- lib/oprt.gi | 14 ++-- lib/oprtglat.gi | 2 +- lib/oprtperm.gi | 2 +- lib/pcgsnice.gi | 2 +- lib/permdeco.gi | 10 +-- lib/relation.gi | 30 ++++----- lib/ringhom.gi | 4 +- lib/schur.gi | 22 +++---- lib/semirel.gi | 2 +- lib/stbcbckt.gi | 2 +- lib/twocohom.gi | 18 +++--- lib/vspchom.gi | 8 +-- 62 files changed, 693 insertions(+), 525 deletions(-) diff --git a/lib/algebra.gi b/lib/algebra.gi index e8457b37e1..df6d32f75f 100644 --- a/lib/algebra.gi +++ b/lib/algebra.gi @@ -3647,7 +3647,7 @@ InstallMethod( CentralIdempotentsOfAlgebra, until k>Length(ideals); - id:= List( ids, e -> PreImagesRepresentative( hom, e ) ); + id:= List( ids, e -> PreImagesRepresentativeNC( hom, e ) ); # Now we lift the idempotents to the big algebra `A'. The # first idempotent is lifted as follows: diff --git a/lib/algfp.gi b/lib/algfp.gi index c65a8ec796..51adff0b6d 100644 --- a/lib/algfp.gi +++ b/lib/algfp.gi @@ -705,7 +705,7 @@ InstallHandlingByNiceBasis( "IsFpAlgebraElementsSpace", rec( if hom = fail then TryNextMethod(); fi; - return PreImagesRepresentative( hom, r ); + return PreImagesRepresentativeNC( hom, r ); end ) ); diff --git a/lib/alghom.gi b/lib/alghom.gi index 8dc79c6efd..550ac43fd6 100644 --- a/lib/alghom.gi +++ b/lib/alghom.gi @@ -576,16 +576,16 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . for algebra g.m.b.i. +#M PreImagesRepresentativeNC( , ) . . . . . . for algebra g.m.b.i. ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for algebra g.m.b.i., and element", FamRangeEqFamElm, [ IsGeneralMapping and IsAlgebraGeneralMappingByImagesDefaultRep, IsObject ], function( map, elm ) - return PreImagesRepresentative( AsLeftModuleGeneralMappingByImages(map), - elm ); + return PreImagesRepresentativeNC( + AsLeftModuleGeneralMappingByImages(map), elm ); end ); @@ -902,7 +902,7 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesRepresentative( , ) +#M PreImagesRepresentativeNC( , ) ## BindGlobal( "PreImagesRepresentativeOperationAlgebraHomomorphism", function( ophom, mat ) if not IsBound( ophom!.basisImage ) then @@ -915,7 +915,7 @@ BindGlobal( "PreImagesRepresentativeOperationAlgebraHomomorphism", function( oph return mat; end ); -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for an operation algebra homomorphism, and an element", FamRangeEqFamElm, [ IsOperationAlgebraHomomorphismDefaultRep, IsMatrix ], @@ -1076,9 +1076,9 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesRepresentative( , ) +#M PreImagesRepresentativeNC( , ) ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for an alg. hom. from f. p. algebra, and an element", FamRangeEqFamElm, [ IsAlgebraHomomorphismFromFpRep, IsMatrix ], diff --git a/lib/alglie.gi b/lib/alglie.gi index 322e003d6d..d3343f8fc4 100644 --- a/lib/alglie.gi +++ b/lib/alglie.gi @@ -34,7 +34,7 @@ InstallMethod( LieUpperCentralSeries, # under the natural homomorphism. Add( S, C ); hom:= NaturalHomomorphismByIdeal( L, C ); - C:= PreImages( hom, LieCentre( Range( hom ) ) ); + C:= PreImagesNC( hom, LieCentre( Range( hom ) ) ); #T we would like to get ideals! #T is it possible to teach the hom. that the preimage of an ideal is an ideal? @@ -1706,7 +1706,7 @@ InstallMethod( LieSolvableRadical, quo:= ImagesSource( hom ); r1:= LieSolvableRadical( quo ); B:= BasisVectors( Basis( r1 ) ); - B:= List( B, x -> PreImagesRepresentative( hom, x ) ); + B:= List( B, x -> PreImagesRepresentativeNC( hom, x ) ); Append( B, BasisVectors( Basis( n ) ) ); fi; @@ -2092,7 +2092,7 @@ InstallMethod( DirectSumDecomposition, SetRadicalOfAlgebra( Q, Subalgebra( Q, [ Zero( Q ) ] ) ); id:= List( CentralIdempotentsOfAlgebra( Q ), - x->PreImagesRepresentative(hom,x)); + x->PreImagesRepresentativeNC(hom,x)); # Now we lift the idempotents to the big algebra `A'. The # first idempotent is lifted as follows: @@ -4017,9 +4017,9 @@ InstallMethod( ImagesRepresentative, ########################################################################### ## -#M PreImagesRepresentative( f, x ) +#M PreImagesRepresentativeNC( f, x ) ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for Fp to SCA mapping, and element", FamRangeEqFamElm, [ IsFptoSCAMorphism, IsSCAlgebraObj ], 0, @@ -5592,8 +5592,8 @@ InstallMethod( JenningsLieAlgebra, T:= EmptySCTable( dim , Zero(F) , "antisymmetric" ); pimgs := []; for i in [1..dim] do - a:= PreImagesRepresentative( Homs[pos[i]] , - PreImagesRepresentative( hom_pcg[pos[i]], gens[i] ) ); + a:= PreImagesRepresentativeNC( Homs[pos[i]] , + PreImagesRepresentativeNC( hom_pcg[pos[i]], gens[i] ) ); # calculate the p-th power image of `a': @@ -5610,8 +5610,8 @@ InstallMethod( JenningsLieAlgebra, # Calculate the commutator [a,b], and map the result into # the correct homogeneous component. - b:= PreImagesRepresentative( Homs[pos[j]], - PreImagesRepresentative( hom_pcg[pos[j]], gens[j] )); + b:= PreImagesRepresentativeNC( Homs[pos[j]], + PreImagesRepresentativeNC( hom_pcg[pos[j]], gens[j] )); c:= Image( hom_pcg[pos[i] + pos[j]], Image(Homs[pos[i] + pos[j]], a^-1*b^-1*a*b) ); e:= ExtRepOfObj(c); @@ -5788,8 +5788,8 @@ InstallMethod( PCentralLieAlgebra, T:= EmptySCTable( dim , Zero(F) , "antisymmetric" ); pimgs := []; for i in [1..dim] do - a:= PreImagesRepresentative( Homs[pos[i]] , - PreImagesRepresentative( hom_pcg[pos[i]], gens[i] ) ); + a:= PreImagesRepresentativeNC( Homs[pos[i]] , + PreImagesRepresentativeNC( hom_pcg[pos[i]], gens[i] ) ); # calculate the p-th power image of `a': @@ -5807,8 +5807,8 @@ InstallMethod( PCentralLieAlgebra, # Calculate the commutator [a,b], and map the result into # the correct homogeneous component. - b:= PreImagesRepresentative( Homs[pos[j]], - PreImagesRepresentative( hom_pcg[pos[j]], gens[j] )); + b:= PreImagesRepresentativeNC( Homs[pos[j]], + PreImagesRepresentativeNC( hom_pcg[pos[j]], gens[j] )); c:= Image( hom_pcg[pos[i] + pos[j]], Image(Homs[pos[i] + pos[j]], a^-1*b^-1*a*b) ); e:= ExtRepOfObj(c); diff --git a/lib/algrep.gi b/lib/algrep.gi index 8d331feee2..7607190b94 100644 --- a/lib/algrep.gi +++ b/lib/algrep.gi @@ -1212,24 +1212,24 @@ InstallMethod( NaturalHomomorphismBySubAlgebraModule, if IsLeftAlgebraModuleElementCollection( V ) then if IsRightAlgebraModuleElementCollection( V ) then left_op:= function( x, v ) - return ImagesRepresentative( f, x^PreImagesRepresentative( f, v ) ); + return ImagesRepresentative( f, x^PreImagesRepresentativeNC( f, v ) ); end; right_op:= function( v, x ) - return ImagesRepresentative( f, PreImagesRepresentative( f, v )^x ); + return ImagesRepresentative( f, PreImagesRepresentativeNC( f, v )^x ); end; qmod:= BiAlgebraModule( LeftActingAlgebra( V ), RightActingAlgebra( V ), left_op, right_op, quot ); else left_op:= function( x, v ) - return ImagesRepresentative( f, x^PreImagesRepresentative( f, v ) ); + return ImagesRepresentative( f, x^PreImagesRepresentativeNC( f, v ) ); end; qmod:= LeftAlgebraModule( LeftActingAlgebra( V ), left_op, quot); fi; else right_op:= function( v, x ) - return ImagesRepresentative( f, PreImagesRepresentative( f, v )^x ); + return ImagesRepresentative( f, PreImagesRepresentativeNC( f, v )^x ); end; qmod:= RightAlgebraModule( RightActingAlgebra( V ), right_op, quot ); diff --git a/lib/autsr.gi b/lib/autsr.gi index 241cc84115..704f9093dc 100644 --- a/lib/autsr.gi +++ b/lib/autsr.gi @@ -118,7 +118,7 @@ local C,M,p,all,gens,sub,q,hom,fp,rels,new,pre,i,free,cnt; rels:=Filtered(RelatorsOfFpGroup(fp),x->ForAll(ExponentSums(x),x->x mod p=0)); rels:=List(rels,x->ElementOfFpGroup(FamilyObj(One(fp)),x)); new:=RestrictedMapping(nat,C)*hom; - pre:=List(rels,x->PreImagesRepresentative(new,x)); + pre:=List(rels,x->PreImagesRepresentativeNC(new,x)); for i in [1..Length(rels)] do if not pre[i] in sub then Add(all,MappedWord(rels[i], @@ -141,7 +141,7 @@ local ocr,fphom,fpg,free,len,dim,tmp,L0,R,rels,mat,r,RS,i,g,v,cnt; fpg:=FreeGeneratorsOfFpGroup(Range(fphom)); ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(fphom))]; ocr.generators:=List(GeneratorsOfGroup(Range(fphom)), - i->PreImagesRepresentative(fphom,i)); + i->PreImagesRepresentativeNC(fphom,i)); OCAddMatrices(ocr,ocr.generators); OCAddRelations(ocr,ocr.generators); OCAddSumMatrices(ocr,ocr.generators); @@ -274,8 +274,8 @@ BindGlobal("AGSRAutomLift",function(ocr,nat,fhom,miso) # allow to deduce corresponding module aut. t:=ocr.trickrels; phom:=IdentityMapping(ocr.moduleauts); - s:=List(t.gens,x->PreImagesRepresentative(nat,x)); - l:=List(t.gens,x->PreImagesRepresentative(nat,ImagesRepresentative(fhom,x))); + s:=List(t.gens,x->PreImagesRepresentativeNC(nat,x)); + l:=List(t.gens,x->PreImagesRepresentativeNC(nat,ImagesRepresentative(fhom,x))); s:=List(t.rels,x->MappedWord(x,GeneratorsOfGroup(t.free),s)); l:=List(t.rels,x->MappedWord(x,GeneratorsOfGroup(t.free),l)); @@ -294,7 +294,7 @@ BindGlobal("AGSRAutomLift",function(ocr,nat,fhom,miso) Size(Image(phom))); fi; for ep in enum do - e:=PreImagesRepresentative(phom,ep); + e:=PreImagesRepresentativeNC(phom,ep); psim:=e*miso; psim:=psim^-1; w:=-List(v,i->i*psim); @@ -486,7 +486,7 @@ local S,c,hom,q,a,b,i,t,have,ups,new,u,good,abort,clim,worked,pp, cnt:=0; for b in t do - new:=PreImagesRepresentative(hom,b); + new:=PreImagesRepresentativeNC(hom,b); if (pp=false or new^pp in S) and locond(new) then S:=ClosureGroup(S,new); have:=true; @@ -1028,7 +1028,7 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, b:=MTX.BasisRadical(mo); fratsim:=Length(b)=0; if not fratsim then - b:=List(b,x->PreImagesRepresentative(hom,PcElementByExponents(MPcgs,x))); + b:=List(b,x->PreImagesRepresentativeNC(hom,PcElementByExponents(MPcgs,x))); for j in b do N:=ClosureSubgroup(N,b); od; @@ -1129,8 +1129,8 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, if perm in Aperm then return true; fi; - aut:=PreImagesRepresentative(AQiso,perm); - newgens:=List(gens,x->PreImagesRepresentative(comiso, + aut:=PreImagesRepresentativeNC(AQiso,perm); + newgens:=List(gens,x->PreImagesRepresentativeNC(comiso, ImagesRepresentative(aut,ImagesRepresentative(comiso,x)))); mo2:=GModuleByMats(LinearActionLayer(newgens,MPcgs),mo.field); @@ -1163,9 +1163,9 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, if perm in Aperm then return true; fi; - aut:=PreImagesRepresentative(AQiso,perm); + aut:=PreImagesRepresentativeNC(AQiso,perm); newgens:=List(GeneratorsOfGroup(Q), - x->PreImagesRepresentative(q,Image(aut,ImagesRepresentative(q,x)))); + x->PreImagesRepresentativeNC(q,Image(aut,ImagesRepresentative(q,x)))); mo2:=GModuleByMats(LinearActionLayer(newgens,MPcgs),mo.field); return MTX.IsomorphismModules(mo,mo2)<>fail; end; @@ -1175,9 +1175,9 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, if perm in Aperm then return true; fi; - aut:=PreImagesRepresentative(AQiso,perm); + aut:=PreImagesRepresentativeNC(AQiso,perm); newgens:=List(GeneratorsOfGroup(Q), - x->PreImagesRepresentative(q,Image(aut,ImagesRepresentative(q,x)))); + x->PreImagesRepresentativeNC(q,Image(aut,ImagesRepresentative(q,x)))); mo2:=GModuleByMats(LinearActionLayer(newgens,MPcgs),mo.field); iso:=MTX.IsomorphismModules(mo,mo2); if iso=fail then @@ -1234,12 +1234,12 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, # stabilize class k:=SmallGeneratingSet(sub); ac:=OrbitStabilizerAlgorithm(sub,false,false, - k,List(k,x->PreImagesRepresentative(AQiso,x)), + k,List(k,x->PreImagesRepresentativeNC(AQiso,x)), rec(pnt:=j, act:= function(set,phi) #local phi; - #phi:=PreImagesRepresentative(AQiso,perm); + #phi:=PreImagesRepresentativeNC(AQiso,perm); return Set(List(set,x->Image(phi,x))); end, onlystab:=true)); @@ -1367,7 +1367,7 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, GeneratorsOfGroup(rf), List(GeneratorsOfGroup(rf), y->ImagesRepresentative(hom,ImagesRepresentative(j, - PreImagesRepresentative(hom,y))))); + PreImagesRepresentativeNC(hom,y))))); Assert(2,IsBijective(k)); Add(ind,k); od; @@ -1390,7 +1390,7 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, proj:=GroupHomomorphismByImagesNC(AQP,Image(resperm), B[2],List(GeneratorsOfGroup(res),x->ImagesRepresentative(resperm,x))); C:=PreImage(proj,Image(resperm,ind)); - C:=List(SmallGeneratingSet(C),x->PreImagesRepresentative(AQiso,x)); + C:=List(SmallGeneratingSet(C),x->PreImagesRepresentativeNC(AQiso,x)); AQ:=Group(C); SetIsFinite(AQ,true); SetIsGroupOfAutomorphismsFiniteGroup(AQ,true); @@ -1416,7 +1416,7 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, C:=MappingGeneratorsImages(AQiso); if C[2]<>GeneratorsOfGroup(AQP) then C:=[List(GeneratorsOfGroup(AQP), - x->PreImagesRepresentative(AQiso,x)), + x->PreImagesRepresentativeNC(AQiso,x)), GeneratorsOfGroup(AQP)]; fi; for j in u do @@ -1450,7 +1450,7 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, substb:=SmallGeneratingSet(substb); AQP:=Group(substb); SetSize(AQP,B); - C:=[List(substb,x->PreImagesRepresentative(AQiso,x)),substb]; + C:=[List(substb,x->PreImagesRepresentativeNC(AQiso,x)),substb]; fi; od; @@ -1883,7 +1883,7 @@ local d,a,map,cG,nG,nH,i,j,u,v,asAutomorphism,K,L,conj,e1,e2, else gens:=SmallGeneratingSet(api); fi; - pre:=List(gens,x->PreImagesRepresentative(iso,x)); + pre:=List(gens,x->PreImagesRepresentativeNC(iso,x)); map:=RepresentativeAction(SubgroupNC(a,pre),u,v,asAutomorphism); if map=fail then return fail; @@ -1904,6 +1904,6 @@ local d,a,map,cG,nG,nH,i,j,u,v,asAutomorphism,K,L,conj,e1,e2, fi; return GroupHomomorphismByImagesNC(G,H,GeneratorsOfGroup(G), - List(GeneratorsOfGroup(G),x->PreImagesRepresentative(e2, + List(GeneratorsOfGroup(G),x->PreImagesRepresentativeNC(e2, Image(conj,Image(e1,x))))); end); diff --git a/lib/clas.gi b/lib/clas.gi index b933b7d50b..2a27e3cbba 100644 --- a/lib/clas.gi +++ b/lib/clas.gi @@ -395,7 +395,7 @@ local H,cl,a,c; H:=Image(hom,G); cl:=[]; for c in ConjugacyClasses(H) do - a:=ConjugacyClass(G,PreImagesRepresentative(hom,Representative(c))); + a:=ConjugacyClass(G,PreImagesRepresentativeNC(hom,Representative(c))); if HasStabilizerOfExternalSet(c) then SetStabilizerOfExternalSet(a,PreImage(hom,StabilizerOfExternalSet(c))); fi; diff --git a/lib/clashom.gi b/lib/clashom.gi index 201b2cd9b7..16c7c4f9c3 100644 --- a/lib/clashom.gi +++ b/lib/clashom.gi @@ -499,7 +499,7 @@ local clT, # classes T for k in clop do Info(InfoHomClass,1,"lifting class ",Representative(k)); - r:=PreImagesRepresentative(ophom,Representative(k)); + r:=PreImagesRepresentativeNC(ophom,Representative(k)); # try to make r of small order rp:=r^Order(Representative(k)); rp:=RepresentativeAction(M,Concatenation(components), @@ -564,7 +564,7 @@ local clT, # classes T orb:=[]; for p in [1..Length(clTR)] do - repres:=PreImagesRepresentative(projections[i],clTR[p]); + repres:=PreImagesRepresentativeNC(projections[i],clTR[p]); if i=1 or isdirprod or reps[j]*RestrictedPermNC(repres,components[i]) in Mproj[i] then @@ -586,8 +586,8 @@ local clT, # classes T #was: #clTR:=List(clTR,i->ConjugacyClass(localcent_r,i)); - #clTR:=List(clTR,j->[PreImagesRepresentative(projections[i], - # Representative(j)), + #clTR:=List(clTR,j->[PreImagesRepresentativeNC(projections[i], + # Representative(j)), # PreImage(centrhom,Centralizer(j)), # j]); @@ -706,7 +706,7 @@ local clT, # classes T #change the transversal element to map to the representative con:=trans[orpo]*gen; limg:=opfun(repres,con); - con:=con*PreImagesRepresentative(centrhom, + con:=con*PreImagesRepresentativeNC(centrhom, RepresentativeAction(localcent_r, Image(projections[i],limg), Representative(clTR[p][3]))); @@ -798,7 +798,7 @@ local clT, # classes T # centralizers_r-conjugation.) con:=trans[orpo]*gen; limg:=opfun(repres,con); - con:=con*PreImagesRepresentative(centrhom, + con:=con*PreImagesRepresentativeNC(centrhom, RepresentativeAction(localcent_r, Image(projections[i],limg), Representative(orb[p][3]))); @@ -870,7 +870,7 @@ local clT, # classes T # remember the element to try trymap:=[p,(cengen[genpos2]* - PreImagesRepresentative( + PreImagesRepresentativeNC( RestrictedMapping(projections[i], centralizers[j]), RepresentativeAction( @@ -1140,7 +1140,7 @@ local cs, # chief series of G # compute the classes of the simple nonabelian factor by random search hom:=NaturalHomomorphismByNormalSubgroupNC(G,lastM); cl:=ConjugacyClasses(Image(hom)); - cl:=List(cl,i->[PreImagesRepresentative(hom,Representative(i)), + cl:=List(cl,i->[PreImagesRepresentativeNC(hom,Representative(i)), PreImage(hom,StabilizerOfExternalSet(i))]); cs:=Concatenation([G],Filtered(cs,x->IsSubset(lastM,x))); fi; @@ -1207,7 +1207,7 @@ local cs, # chief series of G autos:=List(GeneratorsOfGroup(G), i->GroupHomomorphismByImagesNC(T1,T1,GeneratorsOfGroup(T1), List(GeneratorsOfGroup(T1), - j->Image(Thom,PreImagesRepresentative(Thom,j)^i)))); + j->Image(Thom,PreImagesRepresentativeNC(Thom,j)^i)))); # find (probably another) permutation rep for T1 for which all # automorphisms can be represented by permutations @@ -1268,7 +1268,7 @@ local cs, # chief series of G autos:=List(GeneratorsOfGroup(S), i->GroupHomomorphismByImagesNC(T1,T1,GeneratorsOfGroup(T1), List(GeneratorsOfGroup(T1), - j->Image(Thom,PreImagesRepresentative(Thom,j)^i)))); + j->Image(Thom,PreImagesRepresentativeNC(Thom,j)^i)))); # find (probably another) permutation rep for T1 for which all # automorphisms can be represented by permutations @@ -1288,7 +1288,7 @@ local cs, # chief series of G # define isomorphisms between the components reps:=List([1..n],i-> - PreImagesRepresentative(Qhom,RepresentativeAction(Q,1,i))); + PreImagesRepresentativeNC(Qhom,RepresentativeAction(Q,1,i))); genimages:=[]; for j in GeneratorsOfGroup(G) do @@ -1345,7 +1345,7 @@ local cs, # chief series of G SetSize(F,Size(G)); FM:=GroupHomomorphismByImagesNC(G,F,GeneratorsOfGroup(G),FM); clF:=ConjugacyClassesFittingFreeGroup(F); - clF:=List(clF,x->[PreImagesRepresentative(FM,x[1]),PreImage(FM,x[2])]); + clF:=List(clF,x->[PreImagesRepresentativeNC(FM,x[1]),PreImage(FM,x[2])]); return clF; fi; #fi; @@ -1374,9 +1374,9 @@ local cs, # chief series of G Info(InfoHomClass,1, "homomorphism is faithful for relevant factor, take preimages"); if Size(N)=1 and onlysizes=true then - cl:=List(clF,i->[PreImagesRepresentative(Fhom,i[1]),Size(i[2])]); + cl:=List(clF,i->[PreImagesRepresentativeNC(Fhom,i[1]),Size(i[2])]); else - cl:=List(clF,i->[PreImagesRepresentative(Fhom,i[1]), + cl:=List(clF,i->[PreImagesRepresentativeNC(Fhom,i[1]), PreImage(Fhom,i[2])]); fi; else @@ -1391,7 +1391,7 @@ local cs, # chief series of G for k in clF do # modify the representative with a kernel elm. to project # correctly on the second component - elm:=j[1]*PreImagesRepresentative(FMhom, + elm:=j[1]*PreImagesRepresentativeNC(FMhom, LeftQuotient(Image(Fhom,j[1]),k[1])); zentr:=Intersection(j[2],PreImage(Fhom,k[2])); Assert(3,ForAll(GeneratorsOfGroup(zentr), @@ -1449,7 +1449,7 @@ local cs, # chief series of G if Image(Qhom,elm)=jim then # modify the representative with a kernel elm. to project # correctly on the second component - elm:=l[1]*PreImagesRepresentative(FMhom, + elm:=l[1]*PreImagesRepresentativeNC(FMhom, LeftQuotient(Image(Fhom,l[1]),elm)); zentr:=PreImage(Fhom,k[2]^l1); zentr:=Intersection(zentr,l[2]); @@ -1957,7 +1957,7 @@ local classes, # classes to be constructed, the result c := [h * PcElementByExponentsNC( Npcgs,w*com.factorspace), stabrad,stabfacgens,stabfacimg,subsz,stabrsubsz]; #if reduce<>fail then - # Add(classes,[PreImagesRepresentative(reduce,c[1]), + # Add(classes,[PreImagesRepresentativeNC(reduce,c[1]), # PreImage(reduce,c[2])]); # else @@ -2022,7 +2022,7 @@ BindGlobal("LiftClassesEATrivRep", nsfgens:=NormalIntersection(fants[usent],Group(cl[4])); fasize:=Size(nsfgens); nsfgens:=SmallGeneratingSet(nsfgens); - nsgens:=List(nsfgens,x->PreImagesRepresentative(hom,x)); + nsgens:=List(nsfgens,x->PreImagesRepresentativeNC(hom,x)); nsimgs:=List(Concatenation(pcgs,nsgens),npcgsact); mo:=GModuleByMats(nsimgs,field); if not MTX.IsIrreducible(mo) then @@ -2338,7 +2338,7 @@ local r, #radical if IsPermGroup(Range(hom)) and not IsPermGroup(Source(hom)) then f:=Image(hom,G); cl:=ConjugacyClassesFittingFreeGroup(f:onlysizes:=false); - cl:=List(cl,x->[PreImagesRepresentative(hom,x[1]), + cl:=List(cl,x->[PreImagesRepresentativeNC(hom,x[1]), PreImage(hom,x[2])]); else cl:=ConjugacyClassesFittingFreeGroup(G:onlysizes:=false); @@ -2398,12 +2398,12 @@ local r, #radical if ntrihom then ncl:=[]; for i in cl do - new:=[PreImagesRepresentative(hom,i[1])]; + new:=[PreImagesRepresentativeNC(hom,i[1])]; if not IsInt(i[2]) then Add(new,[]); # no generators in radical yet gens:=SmallGeneratingSet(i[2]); Add(new, - List(gens,x->PreImagesRepresentative(hom,x))); + List(gens,x->PreImagesRepresentativeNC(hom,x))); Add(new,gens); #TODO: PreImage groups? #Add(new,PreImage(hom,i[2])); @@ -2886,10 +2886,10 @@ local r, #radical fi; prereps:=f!.classpreimgs; if not IsBound(prereps[j]) then - prereps[j]:=PreImagesRepresentative(hom,Representative(cl[j])); + prereps[j]:=PreImagesRepresentativeNC(hom,Representative(cl[j])); fi; - r:=PreImagesRepresentative(hom,conj); + r:=PreImagesRepresentativeNC(hom,conj); d:=GeneratorsOfGroup(Centralizer(cl[j])); # Format for cl is: @@ -2897,7 +2897,7 @@ local r, #radical # in factor, 4:conjugator, 5:cenpcgs, # 6:cenfac, 7:cenfacimgs, 8:censize, 9:cenfacsize Add(nreps,[i,i^r,prereps[j],r,[], - List(d,x->PreImagesRepresentative(hom,x)),d, + List(d,x->PreImagesRepresentativeNC(hom,x)),d, radsize*Size(Centralizer(cl[j])), Size(Centralizer(cl[j]))]); od; reps:=nreps; diff --git a/lib/csetgrp.gi b/lib/csetgrp.gi index 9c5955a8f3..c2d37bfba8 100644 --- a/lib/csetgrp.gi +++ b/lib/csetgrp.gi @@ -199,7 +199,7 @@ local cla,clb,i,j,k,bd,r,rep,b2,dc, r:=SmallerDegreePermutationRepresentation(b:cheap); k:=Image(r,b); gens:=MorFindGeneratingSystem(k,MorMaxFusClasses(MorRatClasses(k))); - gens:=List(gens,x->PreImagesRepresentative(r,x)); + gens:=List(gens,x->PreImagesRepresentativeNC(r,x)); else gens:=MorFindGeneratingSystem(b,MorMaxFusClasses(MorRatClasses(b))); fi; @@ -1064,7 +1064,7 @@ local c, flip, maxidx, cano, tryfct, p, r, t, Assert(2,Size(a2)*Size(tra)=Size(b)); SetKernelOfMultiplicativeGeneralMapping(r,a2); - dcs:=List(dcs,x->[PreImagesRepresentative(quot,x[1]),Size(a1)*x[2], + dcs:=List(dcs,x->[PreImagesRepresentativeNC(quot,x[1]),Size(a1)*x[2], PreImage(r,x[3])]); r:=List(dcs,x->x[1]); stabs:=List(dcs,x->x[3]); diff --git a/lib/ctblfuns.gi b/lib/ctblfuns.gi index c648c9401f..eec04e92e4 100644 --- a/lib/ctblfuns.gi +++ b/lib/ctblfuns.gi @@ -2049,8 +2049,8 @@ InstallMethod( InertiaSubgroup, if stab = permgrp then return G; else - return PreImagesSet( GroupHomomorphismByImages( G, permgrp, - GeneratorsOfGroup( G ), perms ), + return PreImagesSetNC( GroupHomomorphismByImages( G, permgrp, + GeneratorsOfGroup( G ), perms ), stab ); fi; end ); diff --git a/lib/ctblgrp.gi b/lib/ctblgrp.gi index 3b41dbb5be..914845923f 100644 --- a/lib/ctblgrp.gi +++ b/lib/ctblgrp.gi @@ -1606,7 +1606,7 @@ local tm,tme,piso,gpcgs,gals,ord,l,l2,f,fgens,rws,pow,pos,i,j,k,gen, # not easily transfer to mod p. k:=Image(piso,TrivialSubgroup(D.galMorphisms)); gpcgs:=Pcgs(k); - gals:=List(gpcgs,i->PreImagesRepresentative(piso,i)); + gals:=List(gpcgs,i->PreImagesRepresentativeNC(piso,i)); ord:=List(gpcgs,i->RelativeOrderOfPcElement(gpcgs,i)); l:=Length(gpcgs); @@ -1827,7 +1827,7 @@ local often,trans,e,neu,i,inv,cent,l,s,s1,x,dom; if dom=fail then x:=D.classreps[inv]; - l:=List(s,i->[x^PreImagesRepresentative(e, + l:=List(s,i->[x^PreImagesRepresentativeNC(e, RepresentativeAction(Image(e),1,i[1])),Size(cent)*Length(i)]); else l:=List(s,i->[dom[i[1]],Size(cent)*Length(i)]); diff --git a/lib/ctblsolv.gi b/lib/ctblsolv.gi index d18f10f6d7..fc787a2bb6 100644 --- a/lib/ctblsolv.gi +++ b/lib/ctblsolv.gi @@ -176,7 +176,7 @@ InstallGlobalFunction( ProjectiveCharDeg, function( G, z, q ) # `N' is a normal subgroup such that `N/' is a chief factor of `G' # of order `i' which is a power of `p'. - N:= PreImagesSet( h, N ); + N:= PreImagesSetNC( h, N ); i:= Size( N ) / oz; p:= Factors( i )[1]; @@ -184,7 +184,7 @@ InstallGlobalFunction( ProjectiveCharDeg, function( G, z, q ) # `c' is a list of complement classes of `N' modulo `z' c:= List( ComplementClassesRepresentatives( ImagesSource( h ), ImagesSet( h, N ) ), - x -> PreImagesSet( h, x ) ); + x -> PreImagesSetNC( h, x ) ); r:= Centralizer( G, N ); for L in c do if IsSubset( L, r ) then @@ -563,7 +563,7 @@ InstallGlobalFunction( CoveringTriplesCharacters, function( G, z ) N:= ChiefSeriesUnderAction( img, N ); N:= N[ Length( N ) - 1 ]; fi; - N:= PreImagesSet( h, N ); + N:= PreImagesSetNC( h, N ); if not IsAbelian( N ) then Info( InfoCharacterTable, 2, @@ -582,9 +582,9 @@ InstallGlobalFunction( CoveringTriplesCharacters, function( G, z ) h:= NaturalHomomorphismByNormalSubgroupNC( G, P ); r:= List( CoveringTriplesCharacters( ImagesSource( h ), ImageElm( h, z ) ), - x -> [ PreImagesSet( h, x[1] ), - PreImagesSet( h, x[2] ), - PreImagesRepresentative( h, x[3] ) ] ); + x -> [ PreImagesSetNC( h, x[1] ), + PreImagesSetNC( h, x[2] ), + PreImagesRepresentativeNC( h, x[3] ) ] ); if p = i then @@ -622,9 +622,9 @@ InstallGlobalFunction( CoveringTriplesCharacters, function( G, z ) c:= Stabilizer( img, zn ); fi; Append( r, List( CoveringTriplesCharacters( c, zn ), - x -> [ PreImagesSet( h, x[1] ), - PreImagesSet( h, x[2] ), - PreImagesRepresentative( h, x[3] ) ] ) ); + x -> [ PreImagesSetNC( h, x[1] ), + PreImagesSetNC( h, x[2] ), + PreImagesRepresentativeNC( h, x[3] ) ] ) ); od; return r; @@ -663,9 +663,9 @@ InstallGlobalFunction( CoveringTriplesCharacters, function( G, z ) img:= ImagesSource( h ); Append( r, List( CoveringTriplesCharacters( img, ImageElm( h, z ) ), - x -> [ PreImagesSet( h, x[1] ), - PreImagesSet( h, x[2] ), - PreImagesRepresentative( h, x[3] ) ] ) ); + x -> [ PreImagesSetNC( h, x[1] ), + PreImagesSetNC( h, x[2] ), + PreImagesRepresentativeNC( h, x[3] ) ] ) ); fi; od; return r; @@ -1067,7 +1067,7 @@ InstallMethod( BaumClausenInfo, for i in [ 2 .. Length( ssr.ds ) ] do j:= NaturalHomomorphismByNormalSubgroupNC( ssr.ds[ i-1 ], ssr.ds[i] ); Append( pcgs, List( SpecialPcgs( ImagesSource( j ) ), - x -> PreImagesRepresentative( j, x ) ) ); + x -> PreImagesRepresentativeNC( j, x ) ) ); od; Append( pcgs, SpecialPcgs( Last(ssr.ds) ) ); G:= ImagesSource( hom ); @@ -1911,7 +1911,7 @@ InstallMethod( BaumClausenInfo, k:= Pcgs( kernel ); pcgs:= PcgsByPcSequence( ElementsFamily( FamilyObj( kernel ) ), Concatenation( List( pcgs, - x -> PreImagesRepresentative( hom, x ) ), + x -> PreImagesRepresentativeNC( hom, x ) ), k ) ); k:= ListWithIdenticalEntries( Length( k ), 0 ); diff --git a/lib/field.gi b/lib/field.gi index f5eadb8ede..a65dd50266 100644 --- a/lib/field.gi +++ b/lib/field.gi @@ -1315,15 +1315,15 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesElm( , ) . . . . . . . . . . . . preimage of an elm +#M PreImagesElmNC( , ) . . . . . . . . . . . . preimage of an elm ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for field homomorphism and element", FamRangeEqFamElm, [ IsFieldHomomorphism, IsObject ], function ( hom, elm ) if IsInjective( hom ) = 1 then - return [ PreImagesRepresentative( hom, elm ) ]; + return [ PreImagesRepresentativeNC( hom, elm ) ]; elif IsZero( elm ) then return Source( hom ); else @@ -1334,15 +1334,14 @@ InstallMethod( PreImagesElm, ############################################################################# ## -#M PreImagesSet( , ) . . . . . . . . . . . . . preimage of a set -## -InstallMethod( PreImagesSet, +#M PreImagesSetNC +InstallMethod( PreImagesSetNC, "for field homomorphism and field", CollFamRangeEqFamElms, [ IsFieldHomomorphism, IsField ], function ( hom, elms ) elms:= FieldByGenerators( List( GeneratorsOfField( elms ), - gen -> PreImagesRepresentative( hom, gen ) ) ); + gen -> PreImagesRepresentativeNC( hom, gen ) ) ); UseSubsetRelation( Source( hom ), elms ); return elms; end ); diff --git a/lib/fitfree.gi b/lib/fitfree.gi index d68681ea93..a683e7964c 100644 --- a/lib/fitfree.gi +++ b/lib/fitfree.gi @@ -81,7 +81,7 @@ local ffs,pcisom,rest,kpc,k,x,ker,r,pool,i,xx,pregens,iso; else iso:=IsomorphismFpGroup(Image(rest,U)); pregens:=List(GeneratorsOfGroup(Range(iso)),x-> - PreImagesRepresentative(rest,PreImagesRepresentative(iso,x))); + PreImagesRepresentativeNC(rest,PreImagesRepresentativeNC(iso,x))); # evaluate relators pool:=List(RelatorsOfFpGroup(Range(iso)), x->MappedWord(x,FreeGeneratorsOfFpGroup(Range(iso)),pregens)); @@ -91,7 +91,7 @@ local ffs,pcisom,rest,kpc,k,x,ker,r,pool,i,xx,pregens,iso; iso:=IsomorphismFpGroup(Image(rest,U)); pregens:=List(GeneratorsOfGroup(Range(iso)),x-> - PreImagesRepresentative(rest,PreImagesRepresentative(iso,x))); + PreImagesRepresentativeNC(rest,PreImagesRepresentativeNC(iso,x))); # evaluate relators pool:=List(RelatorsOfFpGroup(Range(iso)), x->MappedWord(x,FreeGeneratorsOfFpGroup(Range(iso)),pregens)); @@ -135,7 +135,7 @@ local ffs,pcisom,rest,kpc,k,x,ker,r,pool,i,xx,pregens,iso; # od; SetSize(U,Size(Image(rest))*Size(kpc)); k:=InducedPcgs(FamilyPcgs(Image(pcisom)),kpc); - k:=List(k,x->PreImagesRepresentative(pcisom,x)); + k:=List(k,x->PreImagesRepresentativeNC(pcisom,x)); k:=InducedPcgsByPcSequenceNC(ffs.pcgs,k); ker:=SubgroupNC(G,k); SetSize(ker,Size(kpc)); @@ -257,7 +257,7 @@ local ffs,hom,U,rest,ker,r,p,l,i,depths,pcisom,subsz,pcimgs; pcimgs:=List(ipcgs,x->ImagesRepresentative(ffs.pcisom,x)); ker:=SubgroupNC(G,List(MinimalGeneratingSet(Group(pcimgs,One(Range(ffs.pcisom)))), - x->PreImagesRepresentative(ffs.pcisom,x))); + x->PreImagesRepresentativeNC(ffs.pcisom,x))); SetPcgs(ker,ipcgs); if Length(ipcgs)=0 then SetSize(ker,1); @@ -916,8 +916,9 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs,gens; s:=SylowSubgroup(Image(hom),prime); fphom:=IsomorphismFpGroup(s); fp:=Image(fphom); - sf:=List(GeneratorsOfGroup(Image(fphom)),x->PreImagesRepresentative(fphom,x)); - sg:=List(sf,x->PreImagesRepresentative(hom,x)); + sf:=List(GeneratorsOfGroup(Image(fphom)), + x->PreImagesRepresentativeNC(fphom,x)); + sg:=List(sf,x->PreImagesRepresentativeNC(hom,x)); sp:=[]; RUN_IN_GGMBI:=true; # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(Group(sg,One(G)),fp,sg, @@ -1194,7 +1195,7 @@ local s,d,c,act,o,i,j,h,p,hf,img,n,k,ns,all,hl,hcomp, norm:=n); for j in [2..Length(i)] do c[i[j]]:=rec(orbit:=i,orbitpos:=j, - rep:=PreImagesRepresentative(act, + rep:=PreImagesRepresentativeNC(act, RepresentativeAction(Image(act),i[1],i[j])), component:=d[i[j]],hall:=h, norm:=n); od; @@ -1232,7 +1233,7 @@ local s,d,c,act,o,i,j,h,p,hf,img,n,k,ns,all,hl,hcomp, fp:=Range(fphom); gens:=MappingGeneratorsImages(fphom); imgs:=gens[2];gens:=gens[1]; - gens:=List(gens,x->PreImagesRepresentative(act,x)); + gens:=List(gens,x->PreImagesRepresentativeNC(act,x)); # adapt to normalize B gens:=List(gens,x->x/RepresentativeAction(t,b^x,b)); @@ -1280,7 +1281,7 @@ local s,d,c,act,o,i,j,h,p,hf,img,n,k,ns,all,hl,hcomp, fp:=Image(fphom); gens:=MappingGeneratorsImages(fphom); imgs:=gens[2];gens:=gens[1]; - gens:=List(gens,x->PreImagesRepresentative(hom,x)); + gens:=List(gens,x->PreImagesRepresentativeNC(hom,x)); fi; # now run through the candidates for Hall in S @@ -1408,8 +1409,9 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs, for s in HallsFittingFree(Image(hom),pi) do fphom:=IsomorphismFpGroup(s); fp:=Image(fphom); - sf:=List(GeneratorsOfGroup(Image(fphom)),x->PreImagesRepresentative(fphom,x)); - sg:=List(sf,x->PreImagesRepresentative(hom,x)); + sf:=List(GeneratorsOfGroup(Image(fphom)), + x->PreImagesRepresentativeNC(fphom,x)); + sg:=List(sf,x->PreImagesRepresentativeNC(hom,x)); sp:=[]; RUN_IN_GGMBI:=true; # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(Group(sg,One(G)),fp,sg, diff --git a/lib/fldabnum.gi b/lib/fldabnum.gi index 5902772c5e..6fb312be2d 100644 --- a/lib/fldabnum.gi +++ b/lib/fldabnum.gi @@ -1918,9 +1918,9 @@ InstallMethod( PreImageElm, ############################################################################# ## -#M PreImagesElm( , ) . . . . . . for autom. of ab. number fields +#M PreImagesElmNC( , ) . . . . . . for autom. of ab. number fields ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for ANF automorphism and scalar", FamRangeEqFamElm, [ IsFieldHomomorphism and IsANFAutomorphismRep, IsScalar ], @@ -1932,9 +1932,9 @@ InstallMethod( PreImagesElm, ############################################################################# ## -#M PreImagesSet( , ) . . . . . for autom. of ab. number fields +#M PreImagesSetNC( , ) . . . . . for autom. of ab. number fields ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for ANF automorphism and scalar", CollFamRangeEqFamElms, [ IsFieldHomomorphism and IsANFAutomorphismRep, IsField ], @@ -1945,9 +1945,9 @@ InstallMethod( PreImagesSet, ############################################################################# ## -#M PreImagesRepresentative( , ) . for autom. of ab. number fields +#M PreImagesRepresentativeNC( , ) for autom. of ab. number fields ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for ANF automorphism and scalar", FamRangeEqFamElm, [ IsFieldHomomorphism and IsANFAutomorphismRep, IsScalar ], diff --git a/lib/ghom.gi b/lib/ghom.gi index bc217f1e32..8047a39206 100644 --- a/lib/ghom.gi +++ b/lib/ghom.gi @@ -253,9 +253,9 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . . via images -## -InstallMethod( PreImagesRepresentative, "for PBG-Hom", FamRangeEqFamElm, +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . via images + +InstallMethod( PreImagesRepresentativeNC, "for PBG-Hom", FamRangeEqFamElm, [ IsPreimagesByAsGroupGeneralMappingByImages, IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) @@ -264,7 +264,7 @@ function( hom, elm ) # group return ImagesRepresentative( RestrictedInverseGeneralMapping( hom ), elm ); else - return PreImagesRepresentative( AsGroupGeneralMappingByImages( hom ), elm ); + return PreImagesRepresentativeNC( AsGroupGeneralMappingByImages( hom ), elm ); fi; end ); @@ -875,9 +875,9 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . . . for GHBI +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . . . for GHBI ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for GHBI and mult.-elm.-with-inverse", FamRangeEqFamElm, [ IsGroupGeneralMappingByImages, @@ -1225,9 +1225,9 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . for conjugator isomorphism +#M PreImagesRepresentativeNC( , ) . . . . for conjugator isomorphism ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for conjugator isomorphism", FamRangeEqFamElm, [ IsConjugatorIsomorphism, IsMultiplicativeElementWithInverse ], 0, @@ -1238,9 +1238,9 @@ InstallMethod( PreImagesRepresentative, ############################################################################# ## -#M PreImagesSet( , ) . . . . . . . . . for conjugator isomorphism +#M PreImagesSetNC( , ) . . . . . . . . . for conjugator isomorphism ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for conjugator isomorphism, and group", CollFamRangeEqFamElms, [ IsConjugatorIsomorphism, IsGroup ], 0, diff --git a/lib/ghomfp.gi b/lib/ghomfp.gi index fcc83630d9..fb2ce5f073 100644 --- a/lib/ghomfp.gi +++ b/lib/ghomfp.gi @@ -441,7 +441,7 @@ local q,r,tg,dtg,pemb,ugens,g,gi,d,o,gens,genims,i,gr,img,l,mapi; #better: orbit algo #r:=ShallowCopy(RightTransversal(q,qu)); #Sort(r,function(a,b) return 1^a<1^b;end); - #r:=List(r,i->PreImagesRepresentative(beta,i)); + #r:=List(r,i->PreImagesRepresentativeNC(beta,i)); # compute transversal with short words from orbit algorithm on points o:=[1]; @@ -527,9 +527,9 @@ end); ############################################################################# ## -#M PreImagesSet( , ) +#M PreImagesSetNC( , ) ## -InstallMethod( PreImagesSet, "map from (sub)group of fp group", +InstallMethod( PreImagesSetNC, "map from (sub)group of fp group", CollFamRangeEqFamElms, [ IsFromFpGroupHomomorphism,IsGroup ],0, function(hom,u) @@ -718,9 +718,9 @@ end); ############################################################################# ## -#M PreImagesRepresentative +#M PreImagesRepresentativeNC ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "hom. to standard generators of fp group, using 'MappedWord'", FamRangeEqFamElm, [IsToFpGroupHomomorphismByImages,IsMultiplicativeElementWithInverse], @@ -1282,7 +1282,7 @@ local v,aiu,aiv,G,primes,irrel,ma,mau,a,k,gens,imgs,q,dec,deco,piv,co; fi; gens:=SmallGeneratingSet(a); - imgs:=List(gens,x->Image(mau,Image(hom,PreImagesRepresentative(ma,x)))); + imgs:=List(gens,x->Image(mau,Image(hom,PreImagesRepresentativeNC(ma,x)))); q:=GroupHomomorphismByImages(a,Image(mau),gens,imgs); k:=KernelOfMultiplicativeGeneralMapping(q); @@ -1293,7 +1293,7 @@ local v,aiu,aiv,G,primes,irrel,ma,mau,a,k,gens,imgs,q,dec,deco,piv,co; dec:=EpimorphismFromFreeGroup(Group(gens)); deco:=function(x) local i; - x:=ExponentSums(PreImagesRepresentative(dec,x)); + x:=ExponentSums(PreImagesRepresentativeNC(dec,x)); for i in [1..Length(aiv)] do x[i]:=x[i] mod aiv[i]; od; @@ -1330,7 +1330,7 @@ local hom,pcgs,impcgs; impcgs:=FamilyPcgs(Image(hom,M)); pcgs:=PcgsByPcSequenceCons(IsPcgsDefaultRep,IsModuloPcgsFpGroupRep, ElementsFamily(FamilyObj(M)), - List(impcgs,i->PreImagesRepresentative(hom,i)), + List(impcgs,i->PreImagesRepresentativeNC(hom,i)), [] ); pcgs!.hom:=hom; diff --git a/lib/ghompcgs.gi b/lib/ghompcgs.gi index f17db8b36c..78ba75b339 100644 --- a/lib/ghompcgs.gi +++ b/lib/ghompcgs.gi @@ -503,9 +503,9 @@ end); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . . via images +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . via images ## -InstallMethod( PreImagesRepresentative, "method for pcgs hom", +InstallMethod( PreImagesRepresentativeNC, "method for pcgs hom", FamRangeEqFamElm, [ IsToPcGroupHomomorphismByImages,IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) @@ -627,9 +627,9 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . via depth map +#M PreImagesRepresentativeNC( , ) . . . . . . . . . via depth map ## -InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, +InstallMethod( PreImagesRepresentativeNC, FamRangeEqFamElm, [ IsPcgsToPcgsHomomorphism,IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) local exp; diff --git a/lib/ghomperm.gi b/lib/ghomperm.gi index 2f103a6a37..7bf4a40a70 100644 --- a/lib/ghomperm.gi +++ b/lib/ghomperm.gi @@ -11,9 +11,9 @@ ############################################################################# ## -#M PreImagesSet( , ) . for s.p. gen. mapping resp. mult. & inv. +#M PreImagesSetNC( , ) . for s.p. gen. mapping resp. mult. & inv. ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for permgroup homs", CollFamRangeEqFamElms, [ IsPermGroupHomomorphism, IsGroup ], @@ -22,7 +22,7 @@ local genpreimages, pre,kg,sz,ol,orb,pos,dom,one; genpreimages:=GeneratorsOfMagmaWithInverses( elms ); genpreimages:= List(genpreimages, - gen -> PreImagesRepresentative( map, gen ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ); if fail in genpreimages then TryNextMethod(); fi; @@ -1152,7 +1152,7 @@ local r, fgens, gens, kg; fi; fgens:=ShallowCopy(GeneratorsOfGroup(r)); gens:=List(fgens, - i->PreImagesRepresentative(hom2,PreImagesRepresentative(hom1,i))); + i->PreImagesRepresentativeNC(hom2,PreImagesRepresentativeNC(hom1,i))); kg:=GeneratorsOfGroup(KernelOfMultiplicativeGeneralMapping(hom2)); Append(gens,kg); Append(fgens,List(kg,i->One(r))); @@ -1162,9 +1162,9 @@ end); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . for perm group range +#M PreImagesRepresentativeNC( , ) . . . . . for perm group range ## -InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, +InstallMethod( PreImagesRepresentativeNC, FamRangeEqFamElm, [ IsToPermGroupGeneralMappingByImages, IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) @@ -1562,9 +1562,9 @@ InstallMethod( ImagesSource,"constituent homomorphism",true, ############################################################################# ## -#M PreImagesRepresentative( , ) +#M PreImagesRepresentativeNC( , ) ## -InstallMethod( PreImagesRepresentative,"constituent homomorphism", +InstallMethod( PreImagesRepresentativeNC,"constituent homomorphism", FamRangeEqFamElm,[IsConstituentHomomorphism,IsPerm], 0, function( hom, elm ) local D,DP; @@ -1579,9 +1579,9 @@ end); ############################################################################# ## -#M PreImagesSet( , ) . . . . . . . . . . . . . . . . for const hom +#M PreImagesSetNC( , ) . . . . . . . . . . . . . . . for const hom ## -InstallMethod( PreImagesSet, "constituent homomorphism",CollFamRangeEqFamElms, +InstallMethod( PreImagesSetNC, "constituent homomorphism",CollFamRangeEqFamElms, [ IsConstituentHomomorphism, IsPermGroup ], 0, function( hom, I ) local H, # preimage of , result @@ -1594,7 +1594,7 @@ InstallMethod( PreImagesSet, "constituent homomorphism",CollFamRangeEqFamElms, # create the preimage group H := EmptyStabChain( [ ], One( Source( hom ) ) ); S := ConjugateStabChain( StabChainMutable( I ), H, x -> - PreImagesRepresentative( hom, x ), hom!.conperm ^ -1 ); + PreImagesRepresentativeNC( hom, x ), hom!.conperm ^ -1 ); T := H; while IsBound( T.stabilizer ) do AddGeneratorsExtendSchreierTree( T, GeneratorsOfGroup( K ) ); @@ -1817,9 +1817,9 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . for blocks hom +#M PreImagesRepresentativeNC( , ) . . . . . . . . for blocks hom ## -InstallMethod( PreImagesRepresentative, "blocks homomorphism", +InstallMethod( PreImagesRepresentativeNC, "blocks homomorphism", FamRangeEqFamElm, [ IsBlocksHomomorphism, IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) @@ -1869,9 +1869,9 @@ end) ; ############################################################################# ## -#M PreImagesSet( , ) . . . . . . . . . . . . . . . for blocks hom +#M PreImagesSetNC( , ) . . . . . . . . . . . . . . for blocks hom ## -InstallMethod( PreImagesSet, CollFamRangeEqFamElms, +InstallMethod( PreImagesSetNC, CollFamRangeEqFamElms, [ IsBlocksHomomorphism, IsPermGroup ], 0, function( hom, I ) local H; # preimage of under , result @@ -1905,7 +1905,7 @@ InstallGlobalFunction( PreImageSetStabBlocksHomomorphism, function( hom, I ) H := PreImageSetStabBlocksHomomorphism( hom, I.stabilizer ); ChangeStabChain( H, [ pnt ], false ); for gen in I.generators do - pre := PreImagesRepresentative( hom, gen ); + pre := PreImagesRepresentativeNC( hom, gen ); if not IsBound( H.translabels[ pnt ^ pre ] ) then AddGeneratorsExtendSchreierTree( H, [ pre ] ); fi; diff --git a/lib/gpfpiso.gi b/lib/gpfpiso.gi index 202d9419a7..8095dd5be1 100644 --- a/lib/gpfpiso.gi +++ b/lib/gpfpiso.gi @@ -91,7 +91,7 @@ local l,iso,fp,stbc,gens; fp:=IsomorphismFpGroup(l); iso:=GroupHomomorphismByImagesNC(G,Range(fp), List(MappingGeneratorsImages(fp)[1], - i->PreImagesRepresentative(iso,i)), + i->PreImagesRepresentativeNC(iso,i)), MappingGeneratorsImages(fp)[2]); SetIsBijective(iso,true); return iso; @@ -171,8 +171,8 @@ function( G, str ) IsNaturalAlternatingGroup(H); new:=IsomorphismFpGroup(H,"@"); gensH:=List(GeneratorsOfGroup(Image(new)), - i->PreImagesRepresentative(new,i)); - preiH := List( gensH, x -> PreImagesRepresentative( hom, x ) ); + i->PreImagesRepresentativeNC(new,i)); + preiH := List( gensH, x -> PreImagesRepresentativeNC( hom, x ) ); c := Length( gensH ); @@ -190,7 +190,7 @@ function( G, str ) w := MappedWord( rel, gensT, gensE{[1..c]} ); t := MappedWord( rel, gensT, imgsE{[1..c]} ); if not t = One( G ) then - t := PreImagesRepresentative( free, t ); + t := PreImagesRepresentativeNC( free, t ); t := MappedWord( t, gensF, gensE{[c+1..n+c]} ); else t := One( E ); @@ -204,7 +204,7 @@ function( G, str ) w := Comm( gensE[c+j], gensE[i] ); t := Comm( imgsE[c+j], imgsE[i] ); if not t = One( G ) then - t := PreImagesRepresentative( free, t ); + t := PreImagesRepresentativeNC( free, t ); t := MappedWord( t, gensF, gensE{[c+1..n+c]} ); else t := One( E ); @@ -293,7 +293,7 @@ function(g,str,N) gens:=Union(gens,Union(List(ser,SmallGeneratingSet))); fi; if f<>g then - gens:=List(gens,x->PreImagesRepresentative(hom,x)); + gens:=List(gens,x->PreImagesRepresentativeNC(hom,x)); ser:=List(ser,x->PreImage(hom,x)); fi; # change generators to make split @@ -397,7 +397,8 @@ function(g,str,N) fgens:=GeneratorsOfGroup(f); auts:=List(GeneratorsOfGroup(g),i-> GroupHomomorphismByImagesNC(f,f,fgens, - List(fgens,j->Image(hom,PreImagesRepresentative(hom,j)^i)):noassert)); + List(fgens, + j->Image(hom,PreImagesRepresentativeNC(hom,j)^i)):noassert)); for j in auts do SetIsBijective(j,true); od; @@ -426,7 +427,7 @@ function(g,str,N) else a:=IsomorphismFpGroup(sf:noassert); fi; - ad:=List(GeneratorsOfGroup(Range(a)),i->PreImagesRepresentative(a,i)); + ad:=List(GeneratorsOfGroup(Range(a)),i->PreImagesRepresentativeNC(a,i)); lad:=Length(ad); n:=Length(orb); @@ -461,7 +462,7 @@ function(g,str,N) fp:=fg/rels; a:=GroupHomomorphismByImagesNC(f,fp,fgens,GeneratorsOfGroup(fp):noassert); fi; - Append(gens,List(fgens,i->PreImagesRepresentative(hom,i))); + Append(gens,List(fgens,i->PreImagesRepresentativeNC(hom,i))); # here we really want a composed homomorphism, to avoid extra work for # a new stabilizer chain @@ -640,7 +641,7 @@ local fpq, qgens, qreps, fpqg, rels, pcgs, p, f, qimg, idx, nimg, decomp, ngen, fp, hom2, di, source, dih, dec, i, j; fpq:=Range(hom); qgens:=GeneratorsOfGroup(fpq); - qreps:=List(qgens,i->PreImagesRepresentative(hom,i)); + qreps:=List(qgens,i->PreImagesRepresentativeNC(hom,i)); fpqg:=FreeGeneratorsOfFpGroup(fpq); rels:=[]; if IsModuloPcgs(mnsf) then @@ -694,7 +695,7 @@ local fpq, qgens, qreps, fpqg, rels, pcgs, p, f, qimg, idx, nimg, decomp, ngen:=FreeGeneratorsOfFpGroup(p); # This is not really a pcgs, but treated as layer generators the same # way, thus use the same variable name - pcgs:=List(GeneratorsOfGroup(p),i->PreImagesRepresentative(mnsf,i)); + pcgs:=List(GeneratorsOfGroup(p),i->PreImagesRepresentativeNC(mnsf,i)); f:=FreeGroup(Length(fpqg)+Length(pcgs)); qimg:=GeneratorsOfGroup(f){[1..Length(fpqg)]}; idx:=[Length(fpqg)+1..Length(fpqg)+Length(pcgs)]; @@ -966,7 +967,7 @@ function( G, series, str ) gensH := GeneratorsOfGroup( H ); gensH := Filtered( gensH, x -> x <> One(H) ); - preiH := List( gensH, x -> PreImagesRepresentative( hom, x ) ); + preiH := List( gensH, x -> PreImagesRepresentativeNC( hom, x ) ); c := Length( gensH ); # compute presentation of H @@ -989,7 +990,7 @@ function( G, series, str ) w := MappedWord( rel, gensT, gensE{[1..c]} ); t := MappedWord( rel, gensT, imgsE{[1..c]} ); if not t = One( G ) then - t := PreImagesRepresentative( free, t ); + t := PreImagesRepresentativeNC( free, t ); t := MappedWord( t, gensF, gensE{[c+1..n+c]} ); else t := One( E ); @@ -1003,7 +1004,7 @@ function( G, series, str ) w := Comm( gensE[c+j], gensE[i] ); t := Comm( imgsE[c+j], imgsE[i] ); if not t = One( G ) then - t := PreImagesRepresentative( free, t ); + t := PreImagesRepresentativeNC( free, t ); t := MappedWord( t, gensF, gensE{[c+1..n+c]} ); else t := One( E ); @@ -1228,8 +1229,8 @@ local iso,fp,dec,homs,mos,i,j,ffp,imo,m,k,gens,fm,mgens,rules, for r in Rules(k) do left:=MappedWord(r[1],FreeGeneratorsOfFpMonoid(m),monreps); right:=MappedWord(r[2],FreeGeneratorsOfFpMonoid(m),monreps); - diff:=LeftQuotient(PreImagesRepresentative(iso,right), - PreImagesRepresentative(iso,left)); + diff:=LeftQuotient(PreImagesRepresentativeNC(iso,right), + PreImagesRepresentativeNC(iso,left)); diff:=ImagesRepresentative(iso,diff); left:=MappedWord(r[1],FreeGeneratorsOfFpMonoid(m),monreal); @@ -1248,7 +1249,7 @@ local iso,fp,dec,homs,mos,i,j,ffp,imo,m,k,gens,fm,mgens,rules, if reduce(mgens[k])=mgens[k] then right:=fmgens[j]^-1*fmgens[k]*fmgens[j]; #collect - right:=ImagesRepresentative(iso,PreImagesRepresentative(iso,right)); + right:=ImagesRepresentative(iso,PreImagesRepresentativeNC(iso,right)); right:=Product(List(LetterRepAssocWord(UnderlyingElement(right)), x->mgens[Position(nums,x)])); right:=reduce(mgens[j]*right); @@ -1320,7 +1321,7 @@ local pcgs,iso,fp,i,j,gens,numi,ord,fm,fam,mword,k,r,addrule,a,e,m; pcgs:=Pcgs(G); iso:=IsomorphismFpGroup(G); fp:=Range(iso); - if List(GeneratorsOfGroup(fp),x->PreImagesRepresentative(iso,x))<>pcgs then + if List(GeneratorsOfGroup(fp),x->PreImagesRepresentativeNC(iso,x))<>pcgs then Error("pcgs"); fi; gens:=[]; @@ -1520,7 +1521,7 @@ local iso,n,fn,sz,bigcount,tryweyl; iso:=IsomorphismGroups(G,P); if iso<>fail then P:=List(GeneratorsOfGroup(H), - x->PreImagesRepresentative(iso,ImagesRepresentative(isp,x))); + x->PreImagesRepresentativeNC(iso,ImagesRepresentative(isp,x))); iso:=GroupHomomorphismByImagesNC(G,H,P,GeneratorsOfGroup(H)); fi; return iso; @@ -1728,13 +1729,13 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, # force going to pc group, as this will give better ordering isob:=GroupHomomorphismByFunction(borel,Range(cb.fphom), x->ImagesRepresentative(cb.fphom,ImagesRepresentative(pciso,x)), - x->PreImagesRepresentative(pciso,PreImagesRepresentative(cb.fphom,x))); + x->PreImagesRepresentativeNC(pciso,PreImagesRepresentativeNC(cb.fphom,x))); b:=Range(isob); wgens:=GeneratorsOfGroup(weyl); - bgens:=List(GeneratorsOfGroup(b),x->PreImagesRepresentative(isob,x)); + bgens:=List(GeneratorsOfGroup(b),x->PreImagesRepresentativeNC(isob,x)); if newstyle and bgens<>GeneratorsOfGroup(borel) then Error("gens");fi; bpairs:=Concatenation(List(bgens,x->[x,x^-1])); @@ -1879,7 +1880,7 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, x:=UnderlyingElement(ImagesRepresentative(cb.monhom,x)); x:=reduce(x,RelationsOfFpMonoid(monoid),mdag,fail); x:=ElementOfFpMonoid(FamilyObj(One(monoid)),x); - return PreImagesRepresentative(cb.monhom,x); + return PreImagesRepresentativeNC(cb.monhom,x); end; mdag:=EmptyKBDAG(Union(List(FreeGeneratorsOfFpMonoid(monoid), @@ -1924,7 +1925,7 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, x:=UnderlyingElement(ImagesRepresentative(cs.monhom,x)); x:=reduce(x,RelationsOfFpMonoid(Range(cs.monhom)),wdag,fail); x:=ElementOfFpMonoid(FamilyObj(One(Range(cs.monhom))),x); - return PreImagesRepresentative(cs.monhom,x); + return PreImagesRepresentativeNC(cs.monhom,x); end; wdag:=EmptyKBDAG(Union(List(FreeGeneratorsOfFpMonoid(Range(cs.monhom)), @@ -1966,7 +1967,7 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, a:=Group(SmallGeneratingSet(group)); # so nothing stores csetperm:=List(GeneratorsOfGroup(a),x->Permutation(x,rt,OnRight)); iso:=EpimorphismFromFreeGroup(a); - csetperm:=List(bgens,x->MappedWord(PreImagesRepresentative(iso,x), + csetperm:=List(bgens,x->MappedWord(PreImagesRepresentativeNC(iso,x), MappingGeneratorsImages(iso)[1],csetperm)); act:=Group(csetperm,()); @@ -2014,7 +2015,7 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, a:=PositionCanonical(rt,elm); b:=rti[a]; rep:=RepresentativeAction(Image(bhom),a,dcnums[b][1]); - rep:=PreImagesRepresentative(bhom,rep); + rep:=PreImagesRepresentativeNC(bhom,rep); if single then a:=[CanonicalRightCosetElement(ac[1],rt[dcnums[b][1]]),rep]; else @@ -2074,9 +2075,8 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, # a:=Group(SmallGeneratingSet(group)); # so nothing stores # csetperm:=List(GeneratorsOfGroup(a),x->Permutation(x,rt,OnRight)); # iso:=EpimorphismFromFreeGroup(a); -# csetperm:=List(bgens,x->MappedWord(PreImagesRepresentative(iso,x),MappingGeneratorsImages(iso)[1],csetperm)); -# act:=Group(csetperm,()); -# +# csetperm:=List(bgens,x->MappedWord(PreImagesRepresentativeNC(iso,x), +# MappingGeneratorsImages(iso)[1],csetperm)); act:=Group(csetperm,()); # bhom:=GroupHomomorphismByImagesNC(borel,act,bgens,csetperm); # #Assert(0,bhom<>fail); # @@ -2119,7 +2119,7 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, # pos:=rti[PositionCanonical(rt,elm)]; # #rep:=RepresentativeAction(borel,PositionCanonical(rt,elm), # # PositionCanonical(rt,dcreps[pos]),bgens,csetperm,OnPoints); -# rep:=PreImagesRepresentative(bhom, +# rep:=PreImagesRepresentativeNC(bhom, # RepresentativeAction(Range(bhom),PositionCanonical(rt,elm), # PositionCanonical(rt,dcreps[pos]))); # rep:=[elm*rep/dcreps[pos],dcreps[pos],rep^-1]; @@ -2441,7 +2441,7 @@ if rule[1]=rule[2] then return;fi; else # BN-style reductions - pcgs:=List(GeneratorsOfGroup(b),x->PreImagesRepresentative(isob,x)); + pcgs:=List(GeneratorsOfGroup(b),x->PreImagesRepresentativeNC(isob,x)); # remove powers pcgs:=pcgs{ Filtered([1..Length(pcgs)],i->not ForAny([1..i-1], @@ -2455,7 +2455,7 @@ if rule[1]=rule[2] then return;fi; # which elements b*i can we write as i*\tilde b. Then b^i=\tilde b, that # is b\in B\cvap B^(i^-1) - pri:=PreImagesRepresentative(isos,i); + pri:=PreImagesRepresentativeNC(isos,i); stb:=Intersection(borel,borel^(pri^-1)); Info(InfoFpGroup,2,i," ",Size(stb)); @@ -2511,14 +2511,14 @@ if rule[1]=rule[2] then return;fi; Info(InfoFpGroup,3,"borelrun ",Position(wo,i)," of ",Length(wo)); # rewrite i*b*j as \tilde b*k*\hat b. - pri:=PreImagesRepresentative(isos,i); + pri:=PreImagesRepresentativeNC(isos,i); stb:=Intersection(borel^pri,borel); for j in wo do Info(InfoFpGroup,2,"DC:",i,", ",j," from ",Length(rels)); for k in borelelm do #RightTransversal(borel,stb) do - a:=PreImagesRepresentative(isos,i)*k* - PreImagesRepresentative(isos,j); + a:=PreImagesRepresentativeNC(isos,i)*k* + PreImagesRepresentativeNC(isos,j); a:=decomp(a); a:=[nofob(ImagesRepresentative(isob,a[1])), nofow(ImagesRepresentative(isos,a[2])), @@ -2684,7 +2684,7 @@ end); # if List(mg,x->LetterRepAssocWord(UnderlyingElement(x)))<> # List([1..Length(mg)],x->[x]) then Error("gens!"); fi; # pre:=List(mg,x->LetterRepAssocWord(UnderlyingElement( -# PreImagesRepresentative(miso,x)))); +# PreImagesRepresentativeNC(miso,x)))); # if ForAny(pre,x->Length(x)<>1) then Error("double");fi; # Add(l,Concatenation(pre)); # if IsBound(m!.rewritingSystem) then @@ -2896,7 +2896,7 @@ local d,f,group,act,g,sy,b,c,borel,weyl,a,i,iso,ucs,gens,gl; fi; c:=c[1]; a:=SubgroupNC(group,List(GeneratorsOfGroup(weyl), - x->PreImagesRepresentative(c,x))); + x->PreImagesRepresentativeNC(c,x))); Size(a); a!.epiweyl:=weyl; weyl:=a; diff --git a/lib/gpprmsya.gi b/lib/gpprmsya.gi index a88508a2bb..d0af65692e 100644 --- a/lib/gpprmsya.gi +++ b/lib/gpprmsya.gi @@ -1265,7 +1265,7 @@ syll, act, typ, sel, bas, wdom, comp, lperm, other, away, i, j,b0,opg,bp; w:=AutomorphismGroup(b); opg:=NaturalHomomorphismByNormalSubgroupNC(w, InnerAutomorphismsAutomorphismGroup(w)); - ll:=List(AsSSortedList(Image(opg)),x->PreImagesRepresentative(opg,x)); + ll:=List(AsSSortedList(Image(opg)),x->PreImagesRepresentativeNC(opg,x)); ll:=Filtered(ll,IsConjugatorAutomorphism); ll:=List(ll,ConjugatorInnerAutomorphism); pg:=b; diff --git a/lib/gprd.gi b/lib/gprd.gi index e32bf13af7..49b091d983 100644 --- a/lib/gprd.gi +++ b/lib/gprd.gi @@ -715,7 +715,7 @@ InstallGlobalFunction(InnerSubdirectProducts2,function( D, U, V ) # and obtain double coset reps reps := List( DoubleCosets( P, autU, autV ), Representative ); - reps := List( reps, x -> PreImagesRepresentative( gamma, x ) ); + reps := List( reps, x -> PreImagesRepresentativeNC( gamma, x ) ); # loop over automorphisms for rep in reps do @@ -724,9 +724,9 @@ InstallGlobalFunction(InnerSubdirectProducts2,function( D, U, V ) gens := Concatenation( GeneratorsOfGroup( N ), GeneratorsOfGroup( M ) ); for r in GeneratorsOfGroup( UN ) do - g := PreImagesRepresentative( pair[1], r ); + g := PreImagesRepresentativeNC( pair[1], r ); h := Image( iso, Image( rep, r ) ); - h := PreImagesRepresentative( pair[2], h ); + h := PreImagesRepresentativeNC( pair[2], h ); Add( gens, g * h ); od; S := SubgroupNC( D, gens ); @@ -1094,7 +1094,7 @@ local info,map,U,mapfun,P; function(elm) elm:=elm![n]; if n>info.degI then - elm:=PreImagesRepresentative(info.alpha,elm); + elm:=PreImagesRepresentativeNC(info.alpha,elm); fi; return elm; end); @@ -1118,7 +1118,7 @@ local info,map,np; map:=GroupHomomorphismByFunction(G,info.groups[2], function(elm) - return PreImagesRepresentative(info.alpha,elm![np]); + return PreImagesRepresentativeNC(info.alpha,elm![np]); end, false, # not bijective function(elm) @@ -1179,7 +1179,7 @@ local giso,niso,P,gens,a,Go,No,i; N:=Image(niso,N); gens:=[]; for i in GeneratorsOfGroup(G) do - i:=Image(aut,PreImagesRepresentative(giso,i)); + i:=Image(aut,PreImagesRepresentativeNC(giso,i)); i:=InducedAutomorphism(niso,i); Add(gens,i); od; @@ -1220,9 +1220,9 @@ local Go,No,giso,niso,FG,GP,FN,NP,F,GI,NI,rels,i,j,P; N:=Image(niso,N); FG:=FreeGeneratorsOfFpGroup(G); - GP:=List(GeneratorsOfGroup(G),x->PreImagesRepresentative(giso,x)); + GP:=List(GeneratorsOfGroup(G),x->PreImagesRepresentativeNC(giso,x)); FN:=FreeGeneratorsOfFpGroup(N); - NP:=List(GeneratorsOfGroup(N),x->PreImagesRepresentative(niso,x)); + NP:=List(GeneratorsOfGroup(N),x->PreImagesRepresentativeNC(niso,x)); F:=FreeGroup(List(Concatenation(FG,FN),String)); GI:=GeneratorsOfGroup(F){[1..Length(FG)]}; diff --git a/lib/gprdmat.gi b/lib/gprdmat.gi index 2480d861d1..c582173350 100644 --- a/lib/gprdmat.gi +++ b/lib/gprdmat.gi @@ -143,9 +143,9 @@ end); ############################################################################# ## -#M PreImagesRepresentative(,) . . . . . . . . . . . of embedding +#M PreImagesRepresentativeNC(,) . . . . . . . . . . . of embedding ## -InstallMethod(PreImagesRepresentative,"matrix direct product embedding", +InstallMethod(PreImagesRepresentativeNC,"matrix direct product embedding", FamRangeEqFamElm, [ IsEmbeddingDirectProductMatrixGroup, IsMultiplicativeElementWithInverse ], @@ -206,9 +206,9 @@ end); ############################################################################# ## -#M PreImagesRepresentative(,) . . . . . . . . . . . of projection +#M PreImagesRepresentativeNC(,) . . . . . . . . . . . of projection ## -InstallMethod(PreImagesRepresentative,"matrix direct product projection", +InstallMethod(PreImagesRepresentativeNC,"matrix direct product projection", FamRangeEqFamElm, [ IsProjectionDirectProductMatrixGroup, IsMultiplicativeElementWithInverse ],0, @@ -382,9 +382,9 @@ end); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . . of embedding +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . of embedding ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "imprim matrix wreath product embedding", FamRangeEqFamElm, [ IsEmbeddingImprimitiveWreathProductMatrixGroup, IsMultiplicativeElementWithInverse ], 0, diff --git a/lib/gprdpc.gi b/lib/gprdpc.gi index 6994897c39..a17e46436a 100644 --- a/lib/gprdpc.gi +++ b/lib/gprdpc.gi @@ -421,7 +421,7 @@ local pg,ph,kg,kh,ig,ih,mg,mh,S,info; ig:=InducedPcgs(pg,kg); ih:=InducedPcgs(ph,kh); mg:=pg mod ig; - mh:=List(mg,i->PreImagesRepresentative(hh,Image(gh,i))); + mh:=List(mg,i->PreImagesRepresentativeNC(hh,Image(gh,i))); pg:=Concatenation(mg,ig,List(ih,i->One(G))); ph:=Concatenation(mh,List(ig,i->One(H)),ih); S:=SubdirProdPcGroups(G,pg,H,ph); diff --git a/lib/gprdperm.gi b/lib/gprdperm.gi index 327f812adc..36973b6b46 100644 --- a/lib/gprdperm.gi +++ b/lib/gprdperm.gi @@ -169,9 +169,9 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . . of embedding +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . of embedding ## -InstallMethod( PreImagesRepresentative, "perm direct product embedding", +InstallMethod( PreImagesRepresentativeNC, "perm direct product embedding", FamRangeEqFamElm, [ IsEmbeddingDirectProductPermGroup, IsMultiplicativeElementWithInverse ], @@ -292,9 +292,9 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . . of projection +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . of projection ## -InstallMethod( PreImagesRepresentative,"perm direct product projection", +InstallMethod( PreImagesRepresentativeNC,"perm direct product projection", FamRangeEqFamElm, [ IsProjectionDirectProductPermGroup, IsMultiplicativeElementWithInverse ], 0, @@ -388,7 +388,7 @@ InstallMethod( SubdirectProductOp,"permgroup", true, # over the generators of the kernel of $phi_2$. gens := []; for gen in GeneratorsOfGroup( G1 ) do - Add( gens, gen^emb1 * PreImagesRepresentative(phi2,gen^phi1)^emb2 ); + Add( gens, gen^emb1 * PreImagesRepresentativeNC(phi2,gen^phi1)^emb2 ); od; for gen in GeneratorsOfGroup( KernelOfMultiplicativeGeneralMapping( phi2 ) ) do @@ -466,9 +466,9 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . . of projection +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . of projection ## -InstallMethod( PreImagesRepresentative,"perm subdirect product projection", +InstallMethod( PreImagesRepresentativeNC,"perm subdirect product projection", FamRangeEqFamElm, [ IsProjectionSubdirectProductPermGroup, IsMultiplicativeElementWithInverse ], 0, @@ -487,11 +487,11 @@ InstallMethod( PreImagesRepresentative,"perm subdirect product projection", # compute the preimage if 1 = prj!.component then - elm := img ^ info.perms[1] - * PreImagesRepresentative(phi2,img^phi1) ^ info.perms[2]; + elm := img ^ info.perms[1] + * PreImagesRepresentativeNC(phi2,img^phi1) ^ info.perms[2]; else - elm := img ^ info.perms[2] - * PreImagesRepresentative(phi1,img^phi2) ^ info.perms[1]; + elm := img ^ info.perms[2] + * PreImagesRepresentativeNC(phi1,img^phi2) ^ info.perms[1]; fi; # return the preimage @@ -799,9 +799,9 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . . of embedding +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . of embedding ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "imprim perm wreath product embedding", FamRangeEqFamElm, [ IsEmbeddingImprimitiveWreathProductPermGroup, IsMultiplicativeElementWithInverse ], 0, diff --git a/lib/grp.gi b/lib/grp.gi index e46a66da6f..27f3644271 100644 --- a/lib/grp.gi +++ b/lib/grp.gi @@ -515,12 +515,12 @@ local p, hom, reps, as, a, b, ap, bp, ab, ap_bp, ab_p, g, h, H, N; reps := ConjugacyClasses(Image(hom)); reps := List(reps, Representative); reps := Filtered(reps, g -> not IsOne(g)); - reps := List(reps, g -> PreImagesRepresentative(hom, g)); + reps := List(reps, g -> PreImagesRepresentativeNC(hom, g)); as := List(reps, a -> [a,a^p]); for b in Image(hom) do - b := PreImagesRepresentative(hom, b); + b := PreImagesRepresentativeNC(hom, b); bp := b^p; for a in as do ap := a[2]; a := a[1]; @@ -1793,7 +1793,7 @@ local hom,gens; fi; hom:=IsomorphismPermGroup(G); gens:=IndependentGeneratorsOfAbelianGroup(Image(hom,G)); - return List(gens,i->PreImagesRepresentative(hom,i)); + return List(gens,i->PreImagesRepresentativeNC(hom,i)); end); @@ -2090,8 +2090,8 @@ InstallGlobalFunction( SupersolvableResiduumDefault, function( G ) # dual space of the module, w.r.t. `pcgs'. mg:= List( gs, x -> TransposedMat( List( pcgs, y -> one * ExponentsOfPcElement( pcgs, Image( ph, - Image( dh, PreImagesRepresentative( - dh, PreImagesRepresentative(ph,y) )^x ) ) )))^-1); + Image( dh, PreImagesRepresentativeNC( + dh, PreImagesRepresentativeNC(ph,y) )^x ) ) )))^-1); #T inverting is not necessary, or? mg:= Filtered( mg, x -> x <> idm ); @@ -2141,11 +2141,11 @@ InstallGlobalFunction( SupersolvableResiduumDefault, function( G ) # Construct a group element corresponding to # the basis element of the submodule. - Add( tmp2, PreImagesRepresentative( ph, + Add( tmp2, PreImagesRepresentativeNC( ph, PcElementByExponentsNC( pcgs, v ) ) ); od; - Add( ds, PreImagesSet( dh, + Add( ds, PreImagesSetNC( dh, SubgroupNC( df, Concatenation( tmp2, gen ) ) ) ); od; Append( gen, tmp2 ); @@ -2154,14 +2154,14 @@ InstallGlobalFunction( SupersolvableResiduumDefault, function( G ) else # cyclic case - Add( ds, PreImagesSet( dh, + Add( ds, PreImagesSetNC( dh, SubgroupNC( df, AsSSortedList( gen ) ) ) ); fi; od; # Generate the new candidate. - ssr:= PreImagesSet( dh, SubgroupNC( df, AsSSortedList( gen ) ) ); + ssr:= PreImagesSetNC( dh, SubgroupNC( df, AsSSortedList( gen ) ) ); fi; @@ -2392,7 +2392,7 @@ InstallMethod( UpperCentralSeriesOfGroup, Add( S, C ); Info( InfoGroup, 2, "UpperCentralSeriesOfGroup: step ", Length(S) ); hom := NaturalHomomorphismByNormalSubgroupNC( G, C ); - C := PreImages( hom, Centre( Image( hom ) ) ); + C := PreImagesNC( hom, Centre( Image( hom ) ) ); od; if Last(S) = G then @@ -3598,7 +3598,7 @@ InstallMethod( HallSubgroupOp, iso := IsomorphismPermGroup( G ); H := HallSubgroup( ImagesSource( iso ), pi ); - return PreImagesSet(iso, H); + return PreImagesSetNC(iso, H); end ); @@ -5337,7 +5337,7 @@ InstallMethod (MinimalNormalSubgroups, local hom; hom := NiceMonomorphism (grp); return List (MinimalNormalSubgroups (NiceObject (grp)), - N -> PreImagesSet (hom, N)); + N -> PreImagesSetNC(hom, N)); end); diff --git a/lib/grpcompl.gi b/lib/grpcompl.gi index 9adf68a175..5058cd8610 100644 --- a/lib/grpcompl.gi +++ b/lib/grpcompl.gi @@ -100,11 +100,11 @@ local G,N,K,s, h, q, fpi, factorpres, com, comgens, cen, ocrels, fpcgs, ncom, factorpres:=[FreeGeneratorsOfFpGroup(Range(fpi)), RelatorsOfFpGroup(Range(fpi)), List(GeneratorsOfGroup(Range(fpi)), - i->PreImagesRepresentative(fpi,i))]; - Assert(1,ForAll(factorpres[3],i->Image(h,PreImagesRepresentative(h,i))=i)); + i->PreImagesRepresentativeNC(fpi,i))]; + Assert(1,ForAll(factorpres[3],i->Image(h,PreImagesRepresentativeNC(h,i))=i)); # initialize com:=[G]; - comgens:=[List(factorpres[3],i->PreImagesRepresentative(h,i))]; + comgens:=[List(factorpres[3],i->PreImagesRepresentativeNC(h,i))]; cen:=[s[1]]; ocrels:=false; diff --git a/lib/grpfp.gi b/lib/grpfp.gi index 8f9d97983b..0546a1f18a 100644 --- a/lib/grpfp.gi +++ b/lib/grpfp.gi @@ -319,7 +319,7 @@ local fam,hom; if hom=fail then TryNextMethod(); fi; - return PreImagesRepresentative(hom,Random(rs, Image(hom,gp))); + return PreImagesRepresentativeNC(hom,Random(rs, Image(hom,gp))); end ); ############################################################################# @@ -2031,11 +2031,11 @@ local d,A,B,e1,e2,Ag,Bg,s,sg,u,v,map,sz; # instead of intersecting both preimages with s we only intersect the # intersection - u:=PreImagesSet(Projection(d,1),G!.sub); + u:=PreImagesSetNC(Projection(d,1),G!.sub); if HasSize(B) then SetSize(u,Size(G!.sub)*Size(B)); fi; - v:=PreImagesSet(Projection(d,2),H!.sub); + v:=PreImagesSetNC(Projection(d,2),H!.sub); if HasSize(A) then SetSize(v,Size(H!.sub)*Size(A)); fi; @@ -3167,7 +3167,7 @@ InstallMethod( LowIndexSubgroupsFpGroupIterator, local u, v; u:= NextIterator( iter!.fullIterator ); - v:= PreImagesSet( fpi, u ); + v:= PreImagesSetNC( fpi, u ); SetIndexInWholeGroup( v, IndexInWholeGroup( G ) * IndexInWholeGroup( u ) ); return v; @@ -3236,7 +3236,7 @@ local fpi,u,l,i,a; l:=[]; for i in u do - a:=PreImagesSet(fpi,i); + a:=PreImagesSetNC(fpi,i); SetIndexInWholeGroup(a,IndexInWholeGroup(G)*IndexInWholeGroup(i)); Add(l,a); od; @@ -3379,8 +3379,8 @@ local d,A,B,e1,e2,Ag,Bg,s,sg,u,v; # get both subgroups in the direct product via the projections # instead of intersecting both preimages with s we only intersect the # intersection - u:=PreImagesSet(Projection(d,1),G!.sub); - v:=PreImagesSet(Projection(d,2),H!.sub); + u:=PreImagesSetNC(Projection(d,1),G!.sub); + v:=PreImagesSetNC(Projection(d,2),H!.sub); u:=Intersection(u,s); v:=Intersection(v,s); @@ -5497,7 +5497,7 @@ local G,T,gens,g,reps,ng,index,i,j,ndef,n,iso; subgroup := U, iso:=iso, table:=T, - reps:=List(reps,i->PreImagesRepresentative(iso,i)))); + reps:=List(reps,i->PreImagesRepresentativeNC(iso,i)))); fi; ndef := 1; @@ -5517,7 +5517,7 @@ local G,T,gens,g,reps,ng,index,i,j,ndef,n,iso; subgroup := U, iso:=iso, table:=T, - reps:=List(reps,i->PreImagesRepresentative(iso,i)))); + reps:=List(reps,i->PreImagesRepresentativeNC(iso,i)))); fi; fi; od; diff --git a/lib/grplatt.gi b/lib/grplatt.gi index 5563219bf7..7419486e85 100644 --- a/lib/grplatt.gi +++ b/lib/grplatt.gi @@ -955,7 +955,7 @@ InstallGlobalFunction(LatticeViaRadical,function(arg) #k:=PreImage(hom,a); # make generators of homomorphism fit nicely to presentation gf:=IsomorphismFpGroup(a); - e:=List(MappingGeneratorsImages(gf)[1],x->PreImagesRepresentative(hom,x)); + e:=List(MappingGeneratorsImages(gf)[1],x->PreImagesRepresentativeNC(hom,x)); # we cannot guarantee that the parent contains e, so no # ClosureSubgroup. k:=ClosureGroup(KernelOfMultiplicativeGeneralMapping(hom),e); @@ -2779,7 +2779,7 @@ local fgi,inducedfactorautos,projs,psubs,info,n,l,nl,emb,u,pos, auts:=[]; for i in GeneratorsOfGroup(n) do aut:=GroupHomomorphismByImages(f,f,gens,List(gens,x-> - Image(hom,PreImagesRepresentative(hom,x)^i))); + Image(hom,PreImagesRepresentativeNC(hom,x)^i))); SetIsBijective(aut,true); Add(auts,aut); od; @@ -2856,7 +2856,7 @@ local fgi,inducedfactorautos,projs,psubs,info,n,l,nl,emb,u,pos, for dc in DoubleCosetRepsAndSizes(t[7],ind,t[8]) do # form the subdirect product g:=List(GeneratorsOfGroup(j[1]), - x->x*Image(emb,PreImagesRepresentative(t[5], + x->x*Image(emb,PreImagesRepresentativeNC(t[5], Image(dc[1],Image(iso,x))) )); Append(g,List(GeneratorsOfGroup(t[1]),x->Image(emb,x))); g:=Subgroup(D,g); diff --git a/lib/grpmat.gi b/lib/grpmat.gi index 5766951a76..17eae4f5e0 100644 --- a/lib/grpmat.gi +++ b/lib/grpmat.gi @@ -623,7 +623,7 @@ local gens,s,dom,mon,no; # call the recursive function to do the work gens:= SCMinSmaGens( no, s, [], One( no ), true ).gens; SetMinimalStabChain(G,s); - return List(gens,i->PreImagesRepresentative(mon,i)); + return List(gens,i->PreImagesRepresentativeNC(mon,i)); end); ############################################################################# @@ -660,7 +660,7 @@ local s,dom,mon, img; i->Position(HomeEnumerator(dom),i)))); # call the recursive function to do the work s:= LargestElementStabChain( s, One( img ) ); - return PreImagesRepresentative(mon,s); + return PreImagesRepresentativeNC(mon,s); end); ############################################################################# @@ -699,7 +699,7 @@ local mon,dom,S,o,oimgs,p,i,g; od; # change by corresponding matrix element - e:=PreImagesRepresentative(mon,g)*e; + e:=PreImagesRepresentativeNC(mon,g)*e; S:=S.stabilizer; od; @@ -1202,9 +1202,9 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . for a blow up isomorphism +#M PreImagesRepresentativeNC( , ) . . . for a blow up isomorphism ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for a blow up isomorphism, and a matrix in the range", FamRangeEqFamElm, [ IsBlowUpIsomorphism, IsMatrix ], diff --git a/lib/grpnames.gi b/lib/grpnames.gi index 8220d79e88..11dcafd25e 100644 --- a/lib/grpnames.gi +++ b/lib/grpnames.gi @@ -173,7 +173,7 @@ InstallMethod( NormalComplementNC, i:=0; for gF in IndependentGeneratorsOfAbelianGroup(F) do i := i+1; - g := PreImagesRepresentative(nat, gF); + g := PreImagesRepresentativeNC(nat, gF); R := RightCoset(N, g); # DirectFactorsOfGroup already computed Center and RationalClasses # when calling NormalComplement diff --git a/lib/grpnice.gd b/lib/grpnice.gd index 5a9480fd86..e22d72c39a 100644 --- a/lib/grpnice.gd +++ b/lib/grpnice.gd @@ -363,7 +363,7 @@ BindGlobal( "AttributeMethodByNiceMonomorphismList", function( oper, par ) local nice; nice:= NiceMonomorphism( obj ); return List( oper( NiceObject( obj ) ), - x -> PreImagesRepresentative( nice, x ) ); + x -> PreImagesRepresentativeNC( nice, x ) ); end ); end ); @@ -398,7 +398,7 @@ BindGlobal( "AttributeMethodByNiceMonomorphismCollElm", function( oper, par ) img := ImagesRepresentative( nice, obj2 : actioncanfail:= true ); if img = fail or not ( img in ImagesSource( nice ) and - PreImagesRepresentative( nice, img ) = obj2 ) then + PreImagesRepresentativeNC( nice, img ) = obj2 ) then TryNextMethod(); fi; return oper( NiceObject( obj1 ), img ); @@ -441,7 +441,7 @@ BindGlobal( "AttributeMethodByNiceMonomorphismElmColl", img := ImagesRepresentative( nice, obj1 : actioncanfail:= true ); if img = fail or not (img in ImagesSource( nice ) and - PreImagesRepresentative( nice, img ) = obj1) then + PreImagesRepresentativeNC( nice, img ) = obj1) then TryNextMethod(); fi; return oper( img, NiceObject( obj2 ) ); @@ -525,7 +525,7 @@ BindGlobal( "GroupMethodByNiceMonomorphismCollElm", img := ImagesRepresentative( nice, obj2 : actioncanfail:= true ); if img = fail or not (img in ImagesSource( nice ) and - PreImagesRepresentative( nice, img ) = obj2) then + PreImagesRepresentativeNC( nice, img ) = obj2) then TryNextMethod(); fi; img1 := oper( NiceObject( obj1 ), img ); @@ -613,7 +613,7 @@ BindGlobal( "SubgroupMethodByNiceMonomorphismCollColl", function( oper, par ) img:=ImagesSet( nice, obj2 ); if img = fail or not ( IsSubset( ImagesSource( nice ), img ) and - PreImagesSet( nice, img ) = obj2 ) then + PreImagesSetNC( nice, img ) = obj2 ) then TryNextMethod(); fi; img := oper( NiceObject( obj1 ), img ); @@ -637,7 +637,7 @@ BindGlobal( "SubgroupMethodByNiceMonomorphismCollElm", function( oper, par ) img := ImagesRepresentative( nice, obj2 : actioncanfail:= true ); if img = fail or not ( img in ImagesSource( nice ) and - PreImagesRepresentative (nice , img ) = obj2 ) then + PreImagesRepresentativeNC( nice, img ) = obj2 ) then TryNextMethod(); fi; img1 := oper( NiceObject( obj1 ), img ); @@ -764,7 +764,7 @@ BindGlobal( "GroupSeriesMethodByNiceMonomorphismCollElm", img := ImagesRepresentative( nice, obj2 : actioncanfail:= true ); if img = fail or not ( img in ImagesSource( nice ) and - PreImagesRepresentative( nice, img ) = obj2 ) then + PreImagesRepresentativeNC( nice, img ) = obj2 ) then TryNextMethod(); fi; list := ShallowCopy( oper( NiceObject( obj1 ), img ) ); diff --git a/lib/grpnice.gi b/lib/grpnice.gi index f72d348e81..6e3db2bd6f 100644 --- a/lib/grpnice.gi +++ b/lib/grpnice.gi @@ -212,7 +212,7 @@ function( elm, G ) nice := NiceMonomorphism( G ); img := ImagesRepresentative( nice, elm:actioncanfail:=true ); return img<>fail and img in NiceObject( G ) - and PreImagesRepresentative( nice, img ) = elm; + and PreImagesRepresentativeNC( nice, img ) = elm; end ); @@ -284,7 +284,7 @@ function( obj1, obj2 ) img := ImagesRepresentative( nice, obj2:actioncanfail:=true ); if img = fail or not (img in ImagesSource(nice) and - PreImagesRepresentative(nice,img)=obj2) then + PreImagesRepresentativeNC(nice,img)=obj2) then TryNextMethod(); fi; no:=NiceObject(obj1); @@ -344,10 +344,10 @@ local mon,cl,clg,c,i; cl:=ConjugacyClasses(NiceObject(g)); clg:=[]; for i in cl do - c:=ConjugacyClass(g,PreImagesRepresentative(mon,Representative(i))); + c:=ConjugacyClass(g,PreImagesRepresentativeNC(mon,Representative(i))); c!.niceClass:=i; if HasStabilizerOfExternalSet(i) then - SetStabilizerOfExternalSet(c,PreImages(mon,StabilizerOfExternalSet(i))); + SetStabilizerOfExternalSet(c,PreImagesNC(mon,StabilizerOfExternalSet(i))); fi; Add(clg,c); od; @@ -767,7 +767,7 @@ SubgroupMethodByNiceMonomorphism( SolvableRadical, InstallMethodWithRandomSource( Random, "for a random source and a group handled by nice monomorphism", [ IsRandomSource, IsGroup and IsHandledByNiceMonomorphism ], 0, - {rs, G} -> PreImagesRepresentative( NiceMonomorphism( G ), + {rs, G} -> PreImagesRepresentativeNC( NiceMonomorphism( G ), Random( rs, NiceObject( G ) ) ) ); @@ -783,9 +783,9 @@ local mon,cl,clg,c,i; cl:=RationalClasses(NiceObject(g)); clg:=[]; for i in cl do - c:=RationalClass(g,PreImagesRepresentative(mon,Representative(i))); + c:=RationalClass(g,PreImagesRepresentativeNC(mon,Representative(i))); if HasStabilizerOfExternalSet(i) then - SetStabilizerOfExternalSet(c,PreImages(mon,StabilizerOfExternalSet(i))); + SetStabilizerOfExternalSet(c,PreImagesNC(mon,StabilizerOfExternalSet(i))); fi; if HasGaloisGroup(i) then SetGaloisGroup(c,GaloisGroup(i)); @@ -806,7 +806,7 @@ function(g,u) local mon,rt; mon:=NiceMonomorphism(g); rt:=RightTransversal(ImagesSet(mon,g),ImagesSet(mon,u)); - rt:=List(rt,i->RightCoset(u,PreImagesRepresentative(mon,i))); + rt:=List(rt,i->RightCoset(u,PreImagesRepresentativeNC(mon,i))); return rt; end); @@ -878,7 +878,7 @@ local hom,rep; rep:= RepresentativeAction( NiceObject( G ), ImageElm( hom, a ), ImageElm( hom, b ), OnPoints ); if rep<>fail then - rep:=PreImagesRepresentative(hom,rep); + rep:=PreImagesRepresentativeNC(hom,rep); fi; return rep; end); @@ -972,9 +972,9 @@ end); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . . via images +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . via images ## -InstallMethod( PreImagesRepresentative, "for PBG-Niceo", +InstallMethod( PreImagesRepresentativeNC, "for PBG-Niceo", FamRangeEqFamElm, [ IsPreimagesByAsGroupGeneralMappingByImages and IsNiceMonomorphism, IsMultiplicativeElementWithInverse ], 0, @@ -983,7 +983,7 @@ local p, tmp; # avoid the double dispatch for `AsGroupGeneralMappingByImages' tmp := RUN_IN_GGMBI; RUN_IN_GGMBI:=true; - p:=PreImagesRepresentative( AsGroupGeneralMappingByImages( hom ), elm ); + p:=PreImagesRepresentativeNC( AsGroupGeneralMappingByImages( hom ), elm ); RUN_IN_GGMBI:=tmp; return p; end ); @@ -1078,7 +1078,7 @@ InstallMethod( \[\],"enum-by-niceo", true, function( enum, pos ) local img; img:=enum!.niceEnumerator[pos]; - return PreImagesRepresentative(enum!.morphism,img); + return PreImagesRepresentativeNC(enum!.morphism,img); end); diff --git a/lib/grppc.gi b/lib/grppc.gi index f01a7af92d..9233d045e2 100644 --- a/lib/grppc.gi +++ b/lib/grppc.gi @@ -2147,7 +2147,7 @@ local e, # EAS if iso<>false then V:=PreImage(iso,V); no:=PreImage(iso,no); - ce:=PreImagesRepresentative(iso,ce); + ce:=PreImagesRepresentativeNC(iso,ce); fi; return [V,no,ce]; end ); @@ -2568,7 +2568,7 @@ local q, pcgs, sub, hom, f, ex, C; ex:=ExponentOfPGroupAndElm(f,q); while ex[1]>q do # take the element of highest order in f and take power of its preimage - ex:=PreImagesRepresentative(hom,ex[2]^q); + ex:=PreImagesRepresentativeNC(hom,ex[2]^q); sub:=NormalClosure(G,ClosureSubgroupNC(sub,ex)); hom:=NaturalHomomorphismByNormalSubgroup(G,sub); f:=Range(hom); @@ -2646,7 +2646,7 @@ function(G,p,e) local f; f:=MaximalAbelianQuotient(G); IsAbelian(Image(f)); - return SubgroupByPcgs(G,Pcgs(PreImagesSet(f,Omega(Image(f),p,e)))); + return SubgroupByPcgs(G,Pcgs(PreImagesSetNC(f,Omega(Image(f),p,e)))); end); # Efficiency notes: @@ -2679,7 +2679,7 @@ local z,f; f:=NaturalHomomorphismByNormalSubgroup(G,Subgroup(G,[z])); IsAbelian(Image(f)); # Probably is not, but quick to check - return SubgroupByPcgs(G,Pcgs(PreImagesSet(f,Omega(Image(f),p,e)))); + return SubgroupByPcgs(G,Pcgs(PreImagesSetNC(f,Omega(Image(f),p,e)))); end); # Efficiency Points: @@ -2820,7 +2820,7 @@ InstallMethod (HallSubgroupOp, "via IsomoprhismPcGroup", true, function (grp, pi) local iso; iso := IsomorphismPcGroup (grp); - return PreImagesSet (iso, HallSubgroup (ImagesSource (iso), pi)); + return PreImagesSetNC(iso, HallSubgroup (ImagesSource (iso), pi)); end); @@ -2841,7 +2841,7 @@ InstallMethod (SylowComplementOp, "via IsomoprhismPcGroup", true, function (grp, p) local iso; iso := IsomorphismPcGroup (grp); - return PreImagesSet (iso, SylowComplement (ImagesSource (iso), p)); + return PreImagesSetNC(iso, SylowComplement (ImagesSource (iso), p)); end); diff --git a/lib/grppcaut.gi b/lib/grppcaut.gi index 2840694725..eb3e7a5f51 100644 --- a/lib/grppcaut.gi +++ b/lib/grppcaut.gi @@ -437,7 +437,7 @@ local spec,s,n,M, if d = 1 then hom := IsomorphismPermGroup( B ); pcgs := Pcgs( Image( hom ) ); - pcs := List( pcgs, x -> PreImagesRepresentative( hom, x ) ); + pcs := List( pcgs, x -> PreImagesRepresentativeNC( hom, x ) ); TransferPcgsInfo( B, pcs, RelativeOrders( pcgs ) ); return B; fi; @@ -509,12 +509,12 @@ local spec,s,n,M, Info( InfoOverGr, 1, "computed normalizer of size ", Size(L)); # go back to mat group - B := List( GeneratorsOfGroup(L), x -> PreImagesRepresentative(hom,x) ); + B := List( GeneratorsOfGroup(L), x -> PreImagesRepresentativeNC(hom,x) ); w := PrimitiveRoot(field)* Immutable( IdentityMat( d, field ) ); B := SubgroupNC( S, Concatenation( B, [w] ) ); if IsSolvableGroup( L ) then - pcgs := List( Pcgs(L), x -> PreImagesRepresentative( hom, x ) ); + pcgs := List( Pcgs(L), x -> PreImagesRepresentativeNC( hom, x ) ); Add( pcgs, w ); rels := ShallowCopy( RelativeOrders( Pcgs(L) ) ); Add( rels, p-1 ); @@ -536,7 +536,7 @@ BindGlobal( "CocycleSQ", function( epi, field ) H := Source( epi ); F := Image( epi ); N := KernelOfMultiplicativeGeneralMapping( epi ); - pcsH := List( Pcgs( F ), x -> PreImagesRepresentative( epi, x ) ); + pcsH := List( Pcgs( F ), x -> PreImagesRepresentativeNC( epi, x ) ); pcsN := Pcgs( N ); pcgsH := PcgsByPcSequence( ElementsFamily( FamilyObj( H ) ), Concatenation( pcsH, pcsN ) ); @@ -646,7 +646,7 @@ BindGlobal( "LiftInduciblePair", function( epi, ind, M, weight ) pcgsF := Pcgs( F ); - pcsH := List( pcgsF, x -> PreImagesRepresentative( epi, x ) ); + pcsH := List( pcgsF, x -> PreImagesRepresentativeNC( epi, x ) ); pcsN := Pcgs( N ); pcgsH := PcgsByPcSequence( ElementsFamily( FamilyObj( H ) ), Concatenation( pcsH, pcsN ) ); @@ -656,7 +656,7 @@ BindGlobal( "LiftInduciblePair", function( epi, ind, M, weight ) # use automorphism of F imgsF := List( pcgsF, x -> Image( ind[1], x ) ); opmats := List( imgsF, x -> MappedPcElement( x, pcgsF, M.generators ) ); - imgsF := List( imgsF, x -> PreImagesRepresentative( epi, x ) ); + imgsF := List( imgsF, x -> PreImagesRepresentativeNC( epi, x ) ); # use automorphism of N imgsN := List( pcsN, x -> ExponentsOfPcElement( pcsN, x ) ); @@ -1418,11 +1418,11 @@ InstallGlobalFunction(AutomorphismGroupSolvableGroup,function( G ) hom := ActionHomomorphism( xset, "surjective"); P := Image( hom ); if IsSolvableGroup( P ) then - pcsA := List( Pcgs(P), x -> PreImagesRepresentative( hom, x )); + pcsA := List( Pcgs(P), x -> PreImagesRepresentativeNC( hom, x )); TransferPcgsInfo( A, pcsA, RelativeOrders( Pcgs(P) ) ); else imgs := SmallGeneratingSet( P ); - gens := List( imgs, x -> PreImagesRepresentative( hom, x ) ); + gens := List( imgs, x -> PreImagesRepresentativeNC( hom, x ) ); tmp := Size( A ); A := GroupByGenerators( gens, One( A ) ); SetSize( A, tmp ); @@ -1543,10 +1543,10 @@ InstallGlobalFunction(AutomorphismGroupFrattFreeGroup,function( G ) imgs := []; for i in [1..Length(gensK)] do m := gensU[i]^n; - a := PreImagesRepresentative( hom, m ); + a := PreImagesRepresentativeNC( hom, m ); Add( imgs, a ); od; - l := PreImagesRepresentative( iso, n ); + l := PreImagesRepresentativeNC( iso, n ); Append( imgs, List( gensF, x -> Image( l, x ) ) ); new := GroupHomomorphismByImagesNC( G, G, gensG, imgs ); SetIsBijective( new, true ); diff --git a/lib/grppccom.gi b/lib/grppccom.gi index 2dc5682575..bb59eef42e 100644 --- a/lib/grppccom.gi +++ b/lib/grppccom.gi @@ -19,7 +19,7 @@ local r,img,i,gens,img2; gens:=GeneratorsOfGroup(img); img2:=Image(h[i],G); r[i]:=GroupHomomorphismByImagesNC(img,img2,gens,List(gens,j-> - Image(h[i],PreImagesRepresentative(h[i+1],j)))); + Image(h[i],PreImagesRepresentativeNC(h[i+1],j)))); SetKernelOfMultiplicativeGeneralMapping(r[i], Image(h[i+1],KernelOfMultiplicativeGeneralMapping(h[i]))); img:=img2; @@ -890,7 +890,7 @@ local H, E, cor, a, i, fun2,pcgs,home; #a :=NaturalHomomorphism( G, G / N ); #cor:=PPrimeSetsOC( Image( a ) ); #cor.generators:=List( cor.generators, x -> - # PreImagesRepresentative( a, x ) ); + # PreImagesRepresentativeNC( a, x ) ); cor:=rec(home:=home,generators:=pcgs mod InducedPcgs(pcgs,N)); cor.useCentralSK:=true; fi; diff --git a/lib/grppcext.gi b/lib/grppcext.gi index 4cfb4063a1..bcc5e554a9 100644 --- a/lib/grppcext.gi +++ b/lib/grppcext.gi @@ -378,11 +378,11 @@ local ag, p1iso, agp, p2iso, DP, p1, p2, gens, genimgs, triso,s,i,u,opt, genimgs:=List(gens, i->ImagesRepresentative(Embedding(D,1), - PreImagesRepresentative(p1iso, - PreImagesRepresentative(pc1,ImagesRepresentative(p1,i)))) + PreImagesRepresentativeNC(p1iso, + PreImagesRepresentativeNC(pc1,ImagesRepresentative(p1,i)))) *ImagesRepresentative(Embedding(D,2), - PreImagesRepresentative(p2iso, - PreImagesRepresentative(pc2,ImagesRepresentative(p2,i)))) ); + PreImagesRepresentativeNC(p2iso, + PreImagesRepresentativeNC(pc2,ImagesRepresentative(p2,i)))) ); else opt:=rec(limit:=s,random:=1); @@ -426,9 +426,9 @@ local ag, p1iso, agp, p2iso, DP, p1, p2, gens, genimgs, triso,s,i,u,opt, genimgs:=List(gens, i->ImagesRepresentative(Embedding(D,1), - PreImagesRepresentative(p1iso,ImagesRepresentative(p1,i))) + PreImagesRepresentativeNC(p1iso,ImagesRepresentative(p1,i))) *ImagesRepresentative(Embedding(D,2), - PreImagesRepresentative(p2iso,ImagesRepresentative(p2,i))) ); + PreImagesRepresentativeNC(p2iso,ImagesRepresentative(p2,i))) ); fi; triso:=GroupHomomorphismByImagesNC(DP,D,gens,genimgs); @@ -528,7 +528,7 @@ local G, M, Mgrp, oper, A, B, D, translate, gens, genimgs, triso, K, K1, gens,M.generators); test:=function(perm) local aut,imgs,mat; - aut:=PreImagesRepresentative(triso,perm); + aut:=PreImagesRepresentativeNC(triso,perm); imgs:=List(gens,x->ImagesRepresentative(aut,x)); imgs:=List(imgs,x->ImagesRepresentative(modulehom,x)); mat:=MTX.IsomorphismModules(M,GModuleByMats(imgs,M.field)); @@ -696,9 +696,9 @@ local G, M, Mgrp, oper, A, B, D, translate, gens, genimgs, triso, K, K1, basicact:=function( tup, elm ) local gens; - #gens := List( tup[1], x -> PreImagesRepresentative( elm[1], x ) ); + #gens := List( tup[1], x -> PreImagesRepresentativeNC( elm[1], x ) ); #gens := List( gens, x -> MappedPcElement( x, tup[1], tup[2] ) ); - gens := List( Ggens, x -> PreImagesRepresentative( elm[1], x ) ); + gens := List( Ggens, x -> PreImagesRepresentativeNC( elm[1], x ) ); gens := List( gens, x -> MappedPcElement( x, Ggens, tup ) ); gens := List( gens, x -> x ^ elm[2] ); return gens; @@ -711,10 +711,10 @@ local G, M, Mgrp, oper, A, B, D, translate, gens, genimgs, triso, K, K1, Assert(1,MappingGeneratorsImages(epi)[2]=Ggens); f:=function( tup, elm ) local gens; - #gens := List( tup[1], x -> PreImagesRepresentative( elm[1], x ) ); + #gens := List( tup[1], x -> PreImagesRepresentativeNC( elm[1], x ) ); #gens := List( gens, x -> MappedPcElement( x, tup[1], tup[2] ) ); - gens := List( Ggens, x -> PreImagesRepresentative( elm[1], x ) ); - gens := List( gens, x -> MappedWord( PreImagesRepresentative(epi,x), + gens := List( Ggens, x -> PreImagesRepresentativeNC( elm[1], x ) ); + gens := List( gens, x -> MappedWord( PreImagesRepresentativeNC(epi,x), GeneratorsOfGroup(Source(epi)), tup ) ); gens := List( gens, x -> x ^ elm[2] ); return gens; @@ -730,13 +730,13 @@ local G, M, Mgrp, oper, A, B, D, translate, gens, genimgs, triso, K, K1, elmlist:=[]; tmp:=List(genimgs,x->x[1]); - preimlist:=List(tmp,x->[x,List(Ggens,y->PreImagesRepresentative(x,y))]); + preimlist:=List(tmp,x->[x,List(Ggens,y->PreImagesRepresentativeNC(x,y))]); f:=function( tup, elm ) local gens,p; p:=PositionProperty(preimlist,x->IsIdenticalObj(x[1],elm[1])); if p=fail then - gens := List( Ggens, x -> PreImagesRepresentative( elm[1], x ) ); + gens := List( Ggens, x -> PreImagesRepresentativeNC( elm[1], x ) ); else gens:=preimlist[p][2]; fi; @@ -781,7 +781,7 @@ local G, M, Mgrp, oper, A, B, D, translate, gens, genimgs, triso, K, K1, if elmlist<>fail then tmp:=List(genimgs,x->x[1]); - preimlist:=List(tmp,x->[x,List(Ggens,y->PreImagesRepresentative(x,y))]); + preimlist:=List(tmp,x->[x,List(Ggens,y->PreImagesRepresentativeNC(x,y))]); # ensure we also account for action u:=Group(tup); @@ -911,7 +911,7 @@ BindGlobal( "MatrixOperationOfCPGroup", function( cc, gens ) mats := List( gens, x -> [] ); base := Basis( Image( cc.cohom ) ); - prei := List( base, x -> PreImagesRepresentative( cc.cohom, x ) ); + prei := List( base, x -> PreImagesRepresentativeNC( cc.cohom, x ) ); pcgs := Pcgs( cc.group ); ords := RelativeOrders( pcgs ); @@ -1008,7 +1008,7 @@ function( G, M, C ) return [ExtensionSQ( cc.collector, G, M, 0 )]; elif Dimension( Image(cc.cohom)) = 1 then c := Basis(Image(cc.cohom))[1]; - c := PreImagesRepresentative(cc.cohom, c); + c := PreImagesRepresentativeNC(cc.cohom, c); return [ExtensionSQ( cc.collector, G, M, 0 ), ExtensionSQ( cc.collector, G, M, c )]; fi; @@ -1018,7 +1018,7 @@ function( G, M, C ) # compute orbit of mats on H^2( G, M ) Mgrp := GroupByGenerators( mats ); orbs := OrbitsDomain( Mgrp, Image(cc.cohom), OnRight ); - orbs := List( orbs, x -> PreImagesRepresentative( cc.cohom, x[1] ) ); + orbs := List( orbs, x -> PreImagesRepresentativeNC( cc.cohom, x[1] ) ); ext := List( orbs, x -> ExtensionSQ( cc.collector, G, M, x ) ); return ext; end); @@ -1113,7 +1113,7 @@ BindGlobal( "NonSplitExtensions", function( arg ) red := true; elif Dimension( Image(cc.cohom ) ) = 1 then - c := PreImagesRepresentative(cc.cohom, Basis(Image(cc.cohom))[1]); + c := PreImagesRepresentativeNC(cc.cohom, Basis(Image(cc.cohom))[1]); all := [ExtensionSQ( C, G, M, c)]; red := true; @@ -1121,7 +1121,7 @@ BindGlobal( "NonSplitExtensions", function( arg ) elif IsBound( arg[3] ) and not arg[3] then all := NormedRowVectors( Image(cc.cohom) ); all := List( all, x -> ExtensionSQ(cohom.collector, G, M, - PreImagesRepresentative(cc.cohom,x ))); + PreImagesRepresentativeNC(cc.cohom,x ))); red := false; # sometimes we do not want to reduce @@ -1132,7 +1132,7 @@ BindGlobal( "NonSplitExtensions", function( arg ) then all := NormedRowVectors( Image(cc.cohom) ); all := List( all, x -> ExtensionSQ(cc.collector, G, M, - PreImagesRepresentative(cc.cohom, x ))); + PreImagesRepresentativeNC(cc.cohom, x ))); red := false; # then we want to reduce @@ -1151,7 +1151,7 @@ BindGlobal( "NonSplitExtensions", function( arg ) # create extensions and add info all := List( all, x -> ExtensionSQ(cc.collector, G, M, - PreImagesRepresentative(cc.cohom, x ))); + PreImagesRepresentativeNC(cc.cohom, x ))); fi; if red then diff --git a/lib/grppclat.gi b/lib/grppclat.gi index 4b8113783e..b313ba6359 100644 --- a/lib/grppclat.gi +++ b/lib/grppclat.gi @@ -86,7 +86,7 @@ local f; else aut:= GroupHomomorphismByImagesNC(f,f,GeneratorsOfGroup(f), List(GeneratorsOfGroup(f), - i->Image(epi,Image(aut,PreImagesRepresentative(epi,i))))); + i->Image(epi,Image(aut,PreImagesRepresentativeNC(epi,i))))); SetIsInjective(aut,true); SetIsSurjective(aut,true); fi; @@ -672,7 +672,7 @@ local g, # group # hom:=[]; # for i in func do # hom2:=GroupHomomorphismByImagesNC(g,g,g.generators,List(g.generators, -# j->Image(isom,Image(i,PreImagesRepresentative(isom,j))))); +# j->Image(isom,Image(i,PreImagesRepresentativeNC(isom,j))))); # hom2.isMapping:=true; # Add(hom,hom2); # od; @@ -788,7 +788,7 @@ local g, # group hom:= GroupHomomorphismByImagesNC(f,fa,GeneratorsOfGroup(f), List(GeneratorsOfGroup(f),i-> - Image(hom,PreImagesRepresentative(epi,i)))); + Image(hom,PreImagesRepresentativeNC(epi,i)))); Assert(2,KernelOfMultiplicativeGeneralMapping(hom)=n); # lift the known groups diff --git a/lib/grpperm.gi b/lib/grpperm.gi index 020398dfe5..08f7805298 100644 --- a/lib/grpperm.gi +++ b/lib/grpperm.gi @@ -1592,7 +1592,7 @@ InstallGlobalFunction( SylowSubgroupPermGroup, function( G, p ) O := Orbit( S, D[1] ); f := ActionHomomorphism( S, O,"surjective" ); T := SylowSubgroupPermGroup( Range( f ), p ); - S := PreImagesSet( f, T ); + S := PreImagesSetNC( f, T ); SubtractSet( D, O ); od; return S; @@ -1605,7 +1605,7 @@ InstallGlobalFunction( SylowSubgroupPermGroup, function( G, p ) f := ActionHomomorphism( G, B, OnSets,"surjective" ); T := SylowSubgroupPermGroup( Range( f ), p ); if Size( T ) < Size( Range( f ) ) then - T := PreImagesSet( f, T ); + T := PreImagesSetNC( f, T ); S := SylowSubgroupPermGroup( T , p) ; return S; fi; @@ -1630,7 +1630,7 @@ InstallGlobalFunction( SylowSubgroupPermGroup, function( G, p ) Info(InfoGroup,1,"PermSylow: cycleaction"); f := ActionHomomorphism( C, B, OnSets,"surjective" ); T := SylowSubgroupPermGroup( Range( f ), p ); - S := PreImagesSet( f, T ); + S := PreImagesSetNC( f, T ); return S; end ); diff --git a/lib/grpprmcs.gi b/lib/grpprmcs.gi index c8a8a1166a..8ba3001d28 100644 --- a/lib/grpprmcs.gi +++ b/lib/grpprmcs.gi @@ -1173,7 +1173,7 @@ InstallGlobalFunction( PullbackKernelCSPG, fi; for g in gens do for j in [1..i-1] do - g := PreImagesRepresentative(homlist[i-j],g); + g := PreImagesRepresentativeNC(homlist[i-j],g); od; Add(normals[index],g); Add(factors[index],()); @@ -1193,7 +1193,7 @@ InstallGlobalFunction( PullbackCSPG, function(p,homlist) # compute a preimage of the permutation p in the input group lenhomlist := Length(homlist); for i in [1..lenhomlist] do - p := PreImagesRepresentative(homlist[lenhomlist+1-i],p); + p := PreImagesRepresentativeNC(homlist[lenhomlist+1-i],p); od; return p; end ); @@ -1522,7 +1522,7 @@ InstallMethod( PCoreOp, for g in GeneratorsOfGroup( KernelOfMultiplicativeGeneralMapping( homlist[i] ) ) do for j in [1..i-1] do - g := PreImagesRepresentative(homlist[i-j],g); + g := PreImagesRepresentativeNC(homlist[i-j],g); od; Add(pgenlist,g); od; @@ -1747,7 +1747,7 @@ InstallMethod( SolvableRadical, for g in GeneratorsOfGroup( KernelOfMultiplicativeGeneralMapping( homlist[i] ) ) do for j in [1..i-1] do - g := PreImagesRepresentative(homlist[i-j],g); + g := PreImagesRepresentativeNC(homlist[i-j],g); od; Add(solvable,g); od; @@ -1873,7 +1873,7 @@ InstallMethod( Centre, else order := Size( centr ); cent := IntersectionNormalClosurePermGroup(GG,centr,order*Size(GG)); - cent:= PreImages(tchom,cent); + cent:= PreImagesNC(tchom,cent); Assert( 1, IsAbelian( cent ) ); SetIsAbelian( cent, true ); return cent; @@ -1917,7 +1917,7 @@ InstallMethod( Centre, cent := IntersectionNormalClosurePermGroup ( GG, GroupByGenerators(hgens,()), order*Size(GG) ); if n <> len then - cent:= PreImages( tchom, cent ); + cent:= PreImagesNC( tchom, cent ); fi; Assert( 1, IsAbelian( cent ) ); SetIsAbelian( cent, true ); @@ -2012,7 +2012,7 @@ InstallGlobalFunction( CentralizerNormalCSPG, function(G,N) # handle case of transitive GG directly if Length(significant) = 1 then centrnorm := CentralizerNormalTransCSPG(GG,NN); - return PreImages(tchom,centrnorm); + return PreImagesNC(tchom,centrnorm); fi; # case of intransitive GG @@ -2054,7 +2054,7 @@ InstallGlobalFunction( CentralizerNormalCSPG, function(G,N) if n = len then return central; else - return PreImages(tchom,central); + return PreImagesNC(tchom,central); fi; end ); diff --git a/lib/liefam.gi b/lib/liefam.gi index 6122a753b0..ca6c3161c6 100644 --- a/lib/liefam.gi +++ b/lib/liefam.gi @@ -447,7 +447,7 @@ InstallMethod( ImagesElm, return [ LieObject( elm ) ]; end ); -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for Lie embedding and Lie object in default representation", FamRangeEqFamElm, [ IsGeneralMapping and IsLieEmbeddingRep, diff --git a/lib/mapphomo.gi b/lib/mapphomo.gi index 3e396945ff..fbd38cb004 100644 --- a/lib/mapphomo.gi +++ b/lib/mapphomo.gi @@ -330,9 +330,9 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesElm( , ) . for s.p. gen. mapping resp. mult. & inv. +#M PreImagesElmNC( , ) . for s.p. gen. mapping resp. mult. & inv. ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "method for s.p. general mapping respecting mult. & inv., and element", FamRangeEqFamElm, [ IsSPGeneralMapping and RespectsMultiplication and RespectsInverses, @@ -340,7 +340,7 @@ InstallMethod( PreImagesElm, function( map, elm ) local pre; - pre:= PreImagesRepresentative( map, elm ); + pre:= PreImagesRepresentativeNC( map, elm ); if pre = fail then return []; else @@ -351,9 +351,9 @@ InstallMethod( PreImagesElm, ############################################################################# ## -#M PreImagesSet( , ) . for s.p. gen. mapping resp. mult. & inv. +#M PreImagesSetNC( , ) . for s.p. gen. mapping resp. mult. & inv. ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for s.p. general mapping respecting mult. & inv., and group", CollFamRangeEqFamElms, [ IsSPGeneralMapping and RespectsMultiplication and RespectsInverses, @@ -367,7 +367,7 @@ InstallMethod( PreImagesSet, fi; genpreimages:= List(genpreimages, - gen -> PreImagesRepresentative( map, gen ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ); if fail in genpreimages then TryNextMethod(); fi; @@ -384,7 +384,7 @@ InstallMethod( PreImagesSet, return pre; end ); -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for injective s.p. mapping respecting mult. & inv., and group", CollFamRangeEqFamElms, [ IsSPGeneralMapping and IsMapping and IsInjective and @@ -395,7 +395,7 @@ InstallMethod( PreImagesSet, pre := SubgroupNC( Source( map ), List( GeneratorsOfMagmaWithInverses( elms ), - gen -> PreImagesRepresentative( map, gen ) ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ) ); UseIsomorphismRelation( elms, pre ); return pre; end ); @@ -684,9 +684,9 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesElm( , ) for s.p. gen. mapping resp. add. & add.inv. +#M PreImagesElmNC( , ) for s.p. gen. mapping resp. add. & add.inv. ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "method for s.p. gen. mapping respecting add. & add.inv., and element", FamRangeEqFamElm, [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses, @@ -694,7 +694,7 @@ InstallMethod( PreImagesElm, function( map, elm ) local pre; - pre:= PreImagesRepresentative( map, elm ); + pre:= PreImagesRepresentativeNC( map, elm ); if pre = fail then return []; else @@ -705,9 +705,9 @@ InstallMethod( PreImagesElm, ############################################################################# ## -#M PreImagesSet( , ) for s.p. gen. mapping resp. add. & add.inv. +#M PreImagesSetNC( , ) for s.p. gen. mapp. resp. add. & add.inv. ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for s.p. gen. mapping resp. add. & add.inv., and add. group", CollFamRangeEqFamElms, [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses, @@ -715,7 +715,7 @@ InstallMethod( PreImagesSet, function( map, elms ) local genpreimages; genpreimages:= List( GeneratorsOfAdditiveGroup( elms ), - gen -> PreImagesRepresentative( map, gen ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ); if fail in genpreimages then TryNextMethod(); fi; @@ -890,9 +890,9 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesSet( , ) . . . . for linear mapping and left module +#M PreImagesSetNC( , ) . . . for linear mapping and left module ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for linear mapping and left module", CollFamRangeEqFamElms, [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses @@ -901,7 +901,7 @@ InstallMethod( PreImagesSet, function( map, elms ) local genpreimages; genpreimages:= List( GeneratorsOfLeftModule( elms ), - gen -> PreImagesRepresentative( map, gen ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ); if fail in genpreimages then TryNextMethod(); fi; @@ -984,9 +984,9 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesSet( , ) . . . . . . . . for algebra hom. and FLMLOR +#M PreImagesSetNC( , ) . . . . . . . for algebra hom. and FLMLOR ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for algebra hom. and FLMLOR", CollFamRangeEqFamElms, [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses @@ -995,7 +995,7 @@ InstallMethod( PreImagesSet, function( map, elms ) local genpreimages; genpreimages:= List( GeneratorsOfLeftOperatorRing( elms ), - gen -> PreImagesRepresentative( map, gen ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ); if fail in genpreimages then TryNextMethod(); fi; @@ -1010,9 +1010,9 @@ InstallMethod( PreImagesSet, ############################################################################# ## -#M PreImagesSet( , ) for alg.-with-one hom. and FLMLOR-with-one +#M PreImagesSetNC( , ) for alg-with-one hom. and FLMLOR-with-one ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for algebra-with-one hom. and FLMLOR-with-one", CollFamRangeEqFamElms, [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses @@ -1022,7 +1022,7 @@ InstallMethod( PreImagesSet, function( map, elms ) local genpreimages; genpreimages:= List( GeneratorsOfLeftOperatorRingWithOne( elms ), - gen -> PreImagesRepresentative( map, gen ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ); if fail in genpreimages then TryNextMethod(); fi; diff --git a/lib/mapping.gd b/lib/mapping.gd index 12d2ff39dc..70c0be49a0 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -751,7 +751,7 @@ DeclareAttribute( "ImagesSource", IsGeneralMapping ); ## ## is the set of preimages of the range of the general mapping map. ##

-## delegates to , +## delegates to , ## it is introduced only to store the preimage of map as attribute ## value. ## @@ -968,7 +968,8 @@ DeclareGlobalFunction( "Images" ); ############################################################################# ## -#O PreImagesElm( , ) . all preimages of elm under a gen. mapping +#O PreImagesElm( , ) . . . . . . . . . . . . all preimages of elm +#O PreImagesElmNC( , ) . . . . . . . . . . . under a gen. mapping ## ## <#GAPDoc Label="PreImagesElm"> ## @@ -976,16 +977,22 @@ DeclareGlobalFunction( "Images" ); ## ## ## If elm is an element of the range of the general mapping -## map then returns the set of all +## map then returns the set of all ## preimages of elm under map. ##

## Anything may happen if elm is not an element of the range of ## map. +##

+## In order to improve this state of affairs, +## PreImagesElm has been renamed PreImagesElmNC +## throughout the library, and PreImagesElm now checks that +## elm is an element of the range before calling PreImagesElmNC. ## ## ## <#/GAPDoc> ## DeclareOperation( "PreImagesElm", [ IsGeneralMapping, IsObject ] ); +DeclareOperation( "PreImagesElmNC", [ IsGeneralMapping, IsObject ] ); ############################################################################# @@ -1015,11 +1022,12 @@ DeclareOperation( "PreImageElm", ############################################################################# ## #O PreImagesRepresentative( , ) . . . one preimage of an element -## under a gen. mapping +#O PreImagesRepresentativeNC( , ) . . . . under a general mapping ## ## <#GAPDoc Label="PreImagesRepresentative"> ## ## +## ## ## ## If elm is an element of the range of the general mapping @@ -1030,21 +1038,28 @@ DeclareOperation( "PreImageElm", ##

## Anything may happen if elm is not an element of the range of ## map. +##

+## In order to improve this state of affairs, PreImagesRepresentative +## has been renamed PreImagesRepresentativeNC throughout the library, +## and PreImagesRepresentative now checks that elm is an +## element of the range before calling PreImagesRepresentativeNC. ## ## ## <#/GAPDoc> ## -DeclareOperation( "PreImagesRepresentative", - [ IsGeneralMapping, IsObject ] ); +DeclareOperation( "PreImagesRepresentative", [ IsGeneralMapping, IsObject ] ); +DeclareOperation( "PreImagesRepresentativeNC", [ IsGeneralMapping, IsObject ] ); ############################################################################# ## #O PreImagesSet( , ) +#O PreImagesSetNC( , ) ## ## <#GAPDoc Label="PreImagesSet"> ## ## +## ## ## ## If elms is a subset of the range of the general mapping map @@ -1053,11 +1068,17 @@ DeclareOperation( "PreImagesRepresentative", ##

## Anything may happen if elms is not a subset of the range of ## map. +##

+## In order to improve this state of affairs, PreImagesSet +## has been renamed PreImagesSetNC throughout the library, +## and PreImagesSet now checks that elm is an +## element of the range before calling PreImagesSetNC. ## ## ## <#/GAPDoc> ## DeclareOperation( "PreImagesSet", [ IsGeneralMapping, IsListOrCollection ] ); +DeclareOperation( "PreImagesSetNC", [ IsGeneralMapping, IsListOrCollection ] ); ############################################################################# @@ -1119,18 +1140,27 @@ DeclareGlobalFunction( "PreImage" ); ############################################################################# ## #F PreImages( ) . . . set of preimages of the range of a gen. mapping +#F PreImagesNC( ) . . set of preimages of the range of a gen. mapping #F PreImages(,) . set of preimages of an elm under a gen. mapping -#F PreImages(,) set of preimages of a coll. under a gen. mapping +#F PreImagesNC(,) set of preimages of an elm under a gen. mapping +#F PreImages(,) set of preimages of a coll. under a gen. mapping +#F PreImagesNC(,) set of preimages of a coll. under a gen. mapping ## ## <#GAPDoc Label="PreImages"> ## ## PreImages ## +## ## +## ## +## ## ## ## PreImages( map ) is the preimage of the general mapping @@ -1157,13 +1187,16 @@ DeclareGlobalFunction( "PreImage" ); ## and to resp. when ## called with two arguments. ##

-## If the second argument is not an element or a subset of the range of -## the first argument, an error is signalled. +## In order to improve this state of affairs, PreImages +## has been renamed PreImagesNC throughout the library, +## and PreImages now checks that elm or coll +## belong to the range before calling PreImagesNC. ## ## ## <#/GAPDoc> ## DeclareGlobalFunction( "PreImages" ); +DeclareGlobalFunction( "PreImagesNC" ); ############################################################################# diff --git a/lib/mapping.gi b/lib/mapping.gi index 7ae902e971..f54e58ee2d 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -273,9 +273,9 @@ InstallGlobalFunction( PreImage, function ( arg ) fi; if IsDomain( img ) or IsSSortedList( img ) then - return PreImagesSet( map, img ); + return PreImagesSetNC( map, img ); elif IsHomogeneousList( img ) then - return PreImagesSet( map, Set( img ) ); + return PreImagesSetNC( map, Set( img ) ); fi; # preimage of the empty list @@ -297,10 +297,68 @@ end ); ############################################################################# ## -#F PreImages( ) . . . set of preimages of the range of a gen. mapping -#F PreImages(,) . set of preimages of an elm under a gen. mapping -#F PreImages(,) set of preimages of a coll. under a gen. mapping +#F PreImages() +#F PreImagesNC() . . . set of preimages of the range of a gen. mapping +#F PreImages(,) +#F PreImagesNC(,) set of preimages of an elm under a gen. mapping +#F PreImages(,) +#F PreImagesNC(,) set of preimages of a coll. under a gen. mapping ## +InstallGlobalFunction( PreImagesNC, function ( arg ) + + local map, # mapping , first argument + img; # element , second argument + + # preimage of the range under + if Length( arg ) = 1 then + + return PreImagesRange( arg[1] ); + + elif Length( arg ) = 2 then + + map := arg[1]; + img := arg[2]; + + if not IsGeneralMapping( map ) then + ErrorNoReturn( " must be a general mapping" ); + fi; + + # preimage of a single element under + if FamRangeEqFamElm( FamilyObj( map ), FamilyObj( img ) ) then + if not img in Range( map ) then + ErrorNoReturn( " must be an element of Range()" ); + fi; + return PreImagesElmNC( map, img ); + + # preimage of a collection of elements under + elif CollFamRangeEqFamElms( FamilyObj( map ), FamilyObj( img ) ) then + if not IsSubset( Range( map ), img ) then + ErrorNoReturn( "the collection must be contained in ", + "Range()" ); + fi; + + if IsDomain( img ) or IsSSortedList( img ) then + return PreImagesSetNC( map, img ); + elif IsHomogeneousList( img ) then + return PreImagesSetNC( map, Set( img ) ); + fi; + + # preimage of the empty list + elif IsList( img ) and IsEmpty( img ) then + + return []; + + else + ErrorNoReturn( "the families of the element or collection ", + "and Range() don't match, ", + "maybe is not contained in Range() or ", + "is not a homogeneous list or collection" ); + fi; + fi; + ErrorNoReturn( "usage: PreImagesNC(), PreImagesNC(,), ", + "PreImagesNC(,)" ); +end ); + InstallGlobalFunction( PreImages, function ( arg ) local map, # mapping , first argument @@ -1067,16 +1125,17 @@ InstallMethod( PreImageElm, "for inj. & surj. general mapping, and element", FamRangeEqFamElm, [ IsGeneralMapping and IsInjective and IsSurjective, IsObject ], 0, - PreImagesRepresentative ); + PreImagesRepresentativeNC ); ############################################################################# ## #M PreImagesElm( , ) . . . . . . for general mapping and element +#M PreImagesElmNC( , ) . . . . . for general mapping and element ## ## more or less delegate to `ImagesElm' ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for general mapping with finite source, and element", FamRangeEqFamElm, [ IsGeneralMapping, IsObject ], 0, @@ -1093,12 +1152,26 @@ InstallMethod( PreImagesElm, fi; end ); +InstallMethod( PreImagesElm, + "for general mapping with finite source, and element", + FamRangeEqFamElm, + [ IsGeneralMapping, IsObject ], 0, + function ( map, elm ) + + if not ( elm in Image( map ) ) then + return []; + else + return PreImagesElmNC( map, elm ); + fi; + end ); + ############################################################################# ## -#M PreImagesElm( , ) for const. time access gen. map., and elm. +#M PreImagesElm( , ) . for const. time access gen. map., and elm. +#M PreImagesElmNC( , ) for const. time access gen. map., and elm. ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for constant time access general mapping, and element", FamRangeEqFamElm, [ IsGeneralMapping and IsConstantTimeAccessGeneralMapping, IsObject ], 0, @@ -1113,12 +1186,25 @@ InstallMethod( PreImagesElm, return preimgs; end ); +InstallMethod( PreImagesElm, + "for constant time access general mapping, and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsConstantTimeAccessGeneralMapping, IsObject ], 0, + function( map, elm ) + if not ( elm in Image( map ) ) then + return []; + else + return PreImagesElmNC( map, elm ); + fi; + end ); + ############################################################################# ## #M PreImagesSet( , ) . for general mapping and finite collection +#M PreImagesSetNC( , ) for general mapping and finite collection ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for general mapping, and finite collection", CollFamRangeEqFamElms, [ IsGeneralMapping, IsCollection ], 0, @@ -1129,12 +1215,31 @@ InstallMethod( PreImagesSet, fi; primgs:= []; for elm in Enumerator( elms ) do - UniteSet( primgs, AsList( PreImagesElm( map, elm ) ) ); + UniteSet( primgs, AsList( PreImagesElmNC( map, elm ) ) ); od; return primgs; end ); + InstallMethod( PreImagesSet, + "for general mapping, and finite collection", + CollFamRangeEqFamElms, + [ IsGeneralMapping, IsCollection ], 0, + function( map, elms ) + local im, elm; + if not IsFinite( elms ) then + TryNextMethod(); + fi; + im:= Image( map ); + for elm in Enumerator( elms ) do + if not (elm in im ) then + return []; + fi; + od; + return PreImagesSetNC( map, elms ); + end ); + +InstallMethod( PreImagesSetNC, "for general mapping, and empty list", true, [ IsGeneralMapping, IsList and IsEmpty ], 0, @@ -1142,6 +1247,14 @@ InstallMethod( PreImagesSet, return []; end ); +InstallMethod( PreImagesSet, + "for general mapping, and empty list", + true, + [ IsGeneralMapping, IsList and IsEmpty ], 0, + function( map, elms ) + return []; + end ); + ############################################################################# ## @@ -1151,7 +1264,7 @@ InstallMethod( PreImagesRange, "for general mapping", true, [ IsGeneralMapping ], 0, - map -> PreImagesSet( map, Range( map ) ) ); + map -> PreImagesSetNC( map, Range( map ) ) ); ############################################################################# @@ -1169,6 +1282,7 @@ InstallMethod( PreImagesRange, ############################################################################# ## #M PreImagesRepresentative( , ) . . for s.p. gen. mapping & elm +#M PreImagesRepresentativeNC( , ) . for s.p. gen. mapping & elm ## InstallMethod( PreImagesRepresentative, "for s.p. general mapping, and element", @@ -1178,12 +1292,21 @@ InstallMethod( PreImagesRepresentative, Error( "no default method for s.p. general mapping" ); end ); +InstallMethod( PreImagesRepresentativeNC, + "for s.p. general mapping, and element", + FamRangeEqFamElm, + [ IsSPGeneralMapping, IsObject ], 0, + function( map, elm ) + Error( "no default method for s.p. general mapping" ); + end ); + ############################################################################# ## #M PreImagesRepresentative( , ) +#M PreImagesRepresentativeNC( , ) ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for total non-s.p. general mapping, and element", FamRangeEqFamElm, [ IsNonSPGeneralMapping, IsObject ], 0, @@ -1191,17 +1314,28 @@ InstallMethod( PreImagesRepresentative, local pres; # all preimages of under # get all preimages of under - pres := PreImagesElm( map, elm ); + pres := PreImagesElmNC( map, elm ); # check that has at least one preimage under if IsEmpty( pres ) then - return fail; + return []; fi; # pick one preimage, and return it. return Representative( pres ); end ); +InstallMethod( PreImagesRepresentative, + "for total non-s.p. general mapping, and element", + FamRangeEqFamElm, + [ IsNonSPGeneralMapping, IsObject ], 0, + function( map, elm ) + if not elm in Image( map ) then + return []; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); + ############################################################################# ## @@ -1459,7 +1593,7 @@ InstallMethod( Enumerator, return enum; elif IsFinite( R ) then for elm in Enumerator( R ) do - imgs:= PreImagesElm( map, elm ); + imgs:= PreImagesElmNC( map, elm ); if IsFinite( imgs ) then UniteSet( enum, List( imgs, im -> DirectProductElement( [ im, elm ] ) ) ); else diff --git a/lib/mapprep.gi b/lib/mapprep.gi index 96bf008e8b..67ea3b1233 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -302,17 +302,17 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesElm( , ) . . . . . . . . . . for composition mapping +#M PreImagesElmNC( , ) . . . . . . . . . for composition mapping ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for a composition mapping, and an element", FamRangeEqFamElm, [ IsCompositionMappingRep, IsObject ], 0, function( com, elm ) local im; - im:= PreImagesElm( com!.map2, elm ); + im:= PreImagesElmNC( com!.map2, elm ); if not IsEmpty( im ) then - return PreImagesSet( com!.map1, im ); + return PreImagesSetNC( com!.map1, im ); else return []; fi; @@ -321,17 +321,17 @@ InstallMethod( PreImagesElm, ############################################################################# ## -#M PreImagesSet( , ) . . . . . . . . . . for composition mapping +#M PreImagesSetNC( , ) . . . . . . . . . for composition mapping ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for a composition mapping, and a collection", CollFamRangeEqFamElms, [ IsCompositionMappingRep, IsCollection ], 0, function( com, elms ) local im; - im:= PreImagesSet( com!.map2, elms ); + im:= PreImagesSetNC( com!.map2, elms ); if not IsEmpty( im ) then - return PreImagesSet( com!.map1, im ); + return PreImagesSetNC( com!.map1, im ); else return []; fi; @@ -340,27 +340,27 @@ InstallMethod( PreImagesSet, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . for composition mapping +#M PreImagesRepresentativeNC( , ) . . . . for composition mapping ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for a composition mapping, and an element", FamRangeEqFamElm, [ IsCompositionMappingRep, IsObject ], 0, function( com, elm ) local im, rep; - im:= PreImagesRepresentative( com!.map2, elm ); + im:= PreImagesRepresentativeNC( com!.map2, elm ); if im = fail then # 'elm' has no preimages under 'com!.map2', so it has none under 'com'. return fail; else - im:= PreImagesRepresentative( com!.map1, im ); + im:= PreImagesRepresentativeNC( com!.map1, im ); if im <> fail then return im; fi; # It may happen that only the chosen representative has no preimages. - for im in Enumerator( PreImagesElm( com!.map2, elm ) ) do - rep:= PreImagesRepresentative( com!.map1, im ); + for im in Enumerator( PreImagesElmNC( com!.map2, elm ) ) do + rep:= PreImagesRepresentativeNC( com!.map1, im ); if rep <> fail then return rep; fi; @@ -383,7 +383,7 @@ InstallMethod( KernelOfAdditiveGeneralMapping, if IsInjective( com!.map2 ) then return KernelOfAdditiveGeneralMapping( com!.map1 ); else - return PreImagesSet( com!.map1, + return PreImagesSetNC( com!.map1, KernelOfAdditiveGeneralMapping( com!.map2 ) ); fi; end ); @@ -421,7 +421,7 @@ InstallMethod( KernelOfMultiplicativeGeneralMapping, if IsInjective( com!.map2 ) then return KernelOfMultiplicativeGeneralMapping( com!.map1 ); else - return PreImagesSet( com!.map1, + return PreImagesSetNC( com!.map1, KernelOfMultiplicativeGeneralMapping( com!.map2 ) ); fi; end ); @@ -629,9 +629,9 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . for mapping by function +#M PreImagesRepresentativeNC( , ) . . . . . for mapping by function ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for mapping by function", FamRangeEqFamElm, [ IsMappingByFunctionRep, IsObject ], 0, @@ -659,9 +659,9 @@ InstallMethod( PreImageElm, ############################################################################# ## -#M PreImagesElm( , ) . . . . . . . . . . for mapping by function +#M PreImagesElmNC( , ) . . . . . . . . . . for mapping by function ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for mapping by function", FamRangeEqFamElm, [ IsMappingByFunctionWithInverseRep, IsObject ], 0, @@ -671,9 +671,9 @@ InstallMethod( PreImagesElm, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . for mapping by function +#M PreImagesRepresentativeNC( , ) . . . . for mapping by function ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for mapping by function with inverse", FamRangeEqFamElm, [ IsMappingByFunctionWithInverseRep, IsObject ], 0, @@ -1008,7 +1008,7 @@ InstallMethod( ImagesElm, FamSourceEqFamElm, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsObject ], 0, function ( inv, elm ) - return PreImagesElm( InverseGeneralMapping( inv ), elm ); + return PreImagesElmNC( InverseGeneralMapping( inv ), elm ); end ); @@ -1021,7 +1021,7 @@ InstallMethod( ImagesSet, CollFamSourceEqFamElms, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsCollection ], 0, function ( inv, elms ) - return PreImagesSet( InverseGeneralMapping( inv ), elms ); + return PreImagesSetNC( InverseGeneralMapping( inv ), elms ); end ); @@ -1034,7 +1034,7 @@ InstallMethod( ImagesRepresentative, FamSourceEqFamElm, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsObject ], 0, function ( inv, elm ) - return PreImagesRepresentative( InverseGeneralMapping( inv ), elm ); + return PreImagesRepresentativeNC( InverseGeneralMapping( inv ), elm ); end ); @@ -1054,9 +1054,9 @@ InstallMethod( PreImageElm, ############################################################################# ## -#M PreImagesElm( , ) . . . . . for inverse mapping and element +#M PreImagesElmNC( , ) . . . . for inverse mapping and element ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for an inverse mapping and an element", FamRangeEqFamElm, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsObject ], 0, @@ -1067,9 +1067,9 @@ InstallMethod( PreImagesElm, ############################################################################# ## -#M PreImagesSet( , ) . . for inverse mapping and collection +#M PreImagesSetNC( , ) . . for inverse mapping and collection ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for an inverse mapping and a collection", CollFamRangeEqFamElms, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsCollection ], 0, @@ -1080,9 +1080,9 @@ InstallMethod( PreImagesSet, ############################################################################# ## -#M PreImagesRepresentative( , ) . . for inv. mapping and elm. +#M PreImagesRepresentativeNC( , ) . . for inv. mapping and elm. ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for an inverse mapping and an element", FamRangeEqFamElm, [ IsInverseGeneralMappingRep, IsObject ], 0, @@ -1293,9 +1293,9 @@ InstallMethod( PreImageElm, ############################################################################# ## -#M PreImagesElm( , ) . . . . for identity mapping and element +#M PreImagesElmMC( , ) . . . for identity mapping and element ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for identity mapping and object", FamRangeEqFamElm, [ IsGeneralMapping and IsOne, IsObject ], @@ -1307,9 +1307,9 @@ InstallMethod( PreImagesElm, ############################################################################# ## -#M PreImagesSet( , ) . . . for identity mapping and collection +#M PreImagesSetNC( , ) . . for identity mapping and collection ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for identity mapping and collection", CollFamRangeEqFamElms, [ IsGeneralMapping and IsOne, IsCollection ], @@ -1321,9 +1321,9 @@ InstallMethod( PreImagesSet, ############################################################################# ## -#M PreImagesRepresentative( , ) +#M PreImagesRepresentativeNC( , ) ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for identity mapping and object", FamRangeEqFamElm, [ IsGeneralMapping and IsOne, IsObject ], @@ -1581,9 +1581,9 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesElm( , ) . . . . . for zero mapping and element +#M PreImagesElmNC( , ) . . . . for zero mapping and element ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for zero mapping and object", FamRangeEqFamElm, [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS, @@ -1598,9 +1598,9 @@ InstallMethod( PreImagesElm, ############################################################################# ## -#M PreImagesSet( , ) . . . . for zero mapping and collection +#M PreImagesSetNC( , ) . . . for zero mapping and collection ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for zero mapping and collection", CollFamRangeEqFamElms, [ IsGeneralMapping and IsZero, IsCollection ], SUM_FLAGS, @@ -1615,9 +1615,9 @@ InstallMethod( PreImagesSet, ############################################################################# ## -#M PreImagesRepresentative( , ) +#M PreImagesRepresentativeNC( , ) ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for zero mapping and object", FamRangeEqFamElm, [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS, @@ -1817,15 +1817,15 @@ end ); ############################################################################# ## -#M PreImagesElm( , ) . . . . . . . . . . for restricted mapping +#M PreImagesElmNC( , ) . . . . . . . . . for restricted mapping ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for a restricted mapping, and an element", FamRangeEqFamElm, [ IsGeneralRestrictedMappingRep, IsObject ], 0, function( res, elm ) local preim; - preim:= PreImagesElm( res!.map, elm ); + preim:= PreImagesElmNC( res!.map, elm ); if not ( (HasIsInjective(res) and IsInjective(res)) or (HasIsInjective(res!.map) and IsInjective(res!.map)) ) then preim:=Intersection(Source(res),preim); @@ -1836,15 +1836,15 @@ end ); ############################################################################# ## -#M PreImagesSet( , ) . . . . . . . . . . for restricted mapping +#M PreImagesSetNC( , ) . . . . . . . . . for restricted mapping ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for a restricted mapping, and a collection", CollFamRangeEqFamElms, [ IsGeneralRestrictedMappingRep, IsCollection ], 0, function( res, elms ) local preim; - preim:= PreImagesSet( res!.map, elms ); + preim:= PreImagesSetNC( res!.map, elms ); if not ( (HasIsInjective(res) and IsInjective(res)) or (HasIsInjective(res!.map) and IsInjective(res!.map)) ) then preim:=Intersection(Source(res),preim); @@ -1855,15 +1855,15 @@ InstallMethod( PreImagesSet, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . for restricted mapping +#M PreImagesRepresentativeNC( , ) . . . . for restricted mapping ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for a restricted mapping, and an element", FamRangeEqFamElm, [ IsGeneralRestrictedMappingRep, IsObject ], 0, function( res, elm ) local preim; - preim:= PreImagesRepresentative( res!.map, elm ); + preim:= PreImagesRepresentativeNC( res!.map, elm ); if preim = fail then # 'elm' has no preimages under 'res!.map', so it has none under 'res'. return fail; @@ -1872,7 +1872,7 @@ InstallMethod( PreImagesRepresentative, elif HasIsInjective(res!.map) and IsInjective(res!.map) then return fail; # no other choice else - preim:= PreImages( res!.map, elm ); + preim:= PreImagesNC( res!.map, elm ); return First(preim,x->x in Source(res)); fi; end ); diff --git a/lib/maxsub.gi b/lib/maxsub.gi index e04c94eaa5..d9a9923d6d 100644 --- a/lib/maxsub.gi +++ b/lib/maxsub.gi @@ -182,7 +182,7 @@ BindGlobal("MaximalSubgroupClassesSol",function(G) sel:=Filtered([1..Length(mgi[2])],x->not IsOne(mgi[2][x])); if 4^Length(sel)>Size(Range(ff.factorhom)) then f:=SmallGeneratingSet(Image(ff.factorhom)); - mgi:=[List(f,x->PreImagesRepresentative(ff.factorhom,x)),f]; + mgi:=[List(f,x->PreImagesRepresentativeNC(ff.factorhom,x)),f]; sel:=[1..Length(mgi[1])]; fi; gensG:=mgi[1]{sel}; @@ -195,8 +195,8 @@ BindGlobal("MaximalSubgroupClassesSol",function(G) fam:=FamilyObj(One(Range(fphom))); # just in case the stored group generators differ... wordfpgens:=List(wordgens,x->ElementOfFpGroup(fam,x)); - wordpre:=List(wordfpgens,x->PreImagesRepresentative(ff.factorhom, - PreImagesRepresentative(fphom,x))); + wordpre:=List(wordfpgens,x->PreImagesRepresentativeNC(ff.factorhom, + PreImagesRepresentativeNC(fphom,x))); fphom:=ff.factorhom*fphom; # no assertion as this is not a proper homomorphism, but an inverse # multiplicative map @@ -513,7 +513,7 @@ local hom,embs,s,k,agens,ad,i,j,perm,dia,ggens,e,tgens,d,m,reco,emba,outs,id; m:=[]; d:=SubgroupNC(w,d); for i in e do - j:=PreImagesRepresentative(hom,i^-1); + j:=PreImagesRepresentativeNC(hom,i^-1); Info(InfoLattice,2,"Orders:",Order(i),",",Order(j)); j:=d^j; if donorm then @@ -633,9 +633,9 @@ local dom, o, t1, a1, t1d, proj, reps, ts, ta, tb, s1, i, fix, wnew, max, s, p1, # get the ts corresponding to points proj:=Projection(w); projG:=RestrictedMapping(proj,G); - reps:=List([1..n],i->PreImagesRepresentative(projG,RepresentativeAction(Image(projG),1,i))); + reps:=List([1..n],i->PreImagesRepresentativeNC(projG,RepresentativeAction(Image(projG),1,i))); reps[n+1]:= - PreImagesRepresentative(proj,RepresentativeAction(Image(proj),[1..n],[n+1..2*n],OnSets)); + PreImagesRepresentativeNC(proj,RepresentativeAction(Image(proj),[1..n],[n+1..2*n],OnSets)); for i in [2..n] do j:=reps[i]*reps[n+1]; reps[1^Image(proj,j)]:=j; @@ -665,8 +665,8 @@ local dom, o, t1, a1, t1d, proj, reps, ts, ta, tb, s1, i, fix, wnew, max, s, p1, en1:=Embedding(wnew,1); en2:=Embedding(wnew,2); emb:=List(GeneratorsOfGroup(s),i-> - Image(en1,PreImagesRepresentative(p1,RestrictedPerm(i,ts[1]))) - *Image(en2,PreImagesRepresentative(p2,RestrictedPerm(i,ts[f]))) ); + Image(en1,PreImagesRepresentativeNC(p1,RestrictedPerm(i,ts[1]))) + *Image(en2,PreImagesRepresentativeNC(p2,RestrictedPerm(i,ts[f]))) ); emb:=GroupHomomorphismByImages(s,wnew,GeneratorsOfGroup(s),emb); ma:=MaxesType3(wnew,Image(emb,s),a1,t1,2,false); for i in ma do @@ -699,7 +699,7 @@ local m, fact, fg, reps, ma, idx, nm, embs, proj, kproj, k, ag, agl, ug, # type 4c reps:=List([1..n], - i->PreImagesRepresentative(fact,RepresentativeAction(fg,1,i))); + i->PreImagesRepresentativeNC(fact,RepresentativeAction(fg,1,i))); # get the maximal subgroups of A, intersect with t to get the socle part @@ -758,8 +758,8 @@ local m, fact, fg, reps, ma, idx, nm, embs, proj, kproj, k, ag, agl, ug, #phi:=ActionHomomorphism(fg,u.orbit,OnSets); #ue:=Image(phi,fg); #reps:=List([1..nlb],i->RepresentativeAction(ue,1,i)); - #reps:=List(reps,i->PreImagesRepresentative(phi,i)); - #reps:=List(reps,i->PreImagesRepresentative(fact,i)); + #reps:=List(reps,i->PreImagesRepresentativeNC(phi,i)); + #reps:=List(reps,i->PreImagesRepresentativeNC(fact,i)); #u:=u.stabilizer; uphi:=ActionHomomorphism(Image(fact,u),b); diff --git a/lib/mgmring.gi b/lib/mgmring.gi index 077f27c153..f7a4688a36 100644 --- a/lib/mgmring.gi +++ b/lib/mgmring.gi @@ -1220,7 +1220,7 @@ InstallMethod( ImagesRepresentative, end ); -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for embedding of ring into magma ring, and free magma ring element", FamRangeEqFamElm, [ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ], @@ -1236,7 +1236,7 @@ InstallMethod( PreImagesElm, fi; end ); -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for embedding of ring into magma ring, and free magma ring element", FamRangeEqFamElm, [ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ], @@ -1324,7 +1324,7 @@ InstallMethod( ImagesRepresentative, end ); -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for embedding of magma into magma ring, and free magma ring element", FamRangeEqFamElm, [ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ], @@ -1340,7 +1340,7 @@ InstallMethod( PreImagesElm, fi; end ); -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for embedding of magma into magma ring, and free magma ring element", FamRangeEqFamElm, [ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ], diff --git a/lib/morpheus.gi b/lib/morpheus.gi index 0e92772399..9cb2957e14 100644 --- a/lib/morpheus.gi +++ b/lib/morpheus.gi @@ -748,10 +748,10 @@ local hom, gens, c, ran, r, cen, img, u, orbs, function(perm) if perm in store[1] then return ConjugatorAutomorphismNC(g, - PreImagesRepresentative(img[2],perm)); + PreImagesRepresentativeNC(img[2],perm)); fi; return GroupHomomorphismByImagesNC(g,g,GeneratorsOfGroup(g), - List(store[2],i->PreImagesRepresentative(img[2],i^perm))); + List(store[2],i->PreImagesRepresentativeNC(img[2],i^perm))); end); if bestdegPreImagesRepresentative(store[3],i^perm))); + List(store[4],i->PreImagesRepresentativeNC(store[3],i^perm))); end); if bestdegPreImagesRepresentative(gens,i)); + i->PreImagesRepresentativeNC(gens,i)); Ggc:=List(gens,i->First(Gcl,j->ForAny(j,j->ForAny(j.classes,k->i in k)))); combi:=List(Ggc,i->Concatenation(List(i,i->i.classes))); bcl:=ShallowCopy(combi); @@ -2106,7 +2106,7 @@ local d,id,H,iso,aut,auts,i,all,hom,field,dim,P,diag,mats,gens,gal; fi; aut:=GroupGeneralMappingByImages(G,G,gens, List(gens, - x->PreImagesRepresentative(iso,Image(iso,x)^(1,2)))); + x->PreImagesRepresentativeNC(iso,Image(iso,x)^(1,2)))); auts:=[aut]; all:=true; fi; @@ -2167,7 +2167,7 @@ local d,id,H,iso,aut,auts,i,all,hom,field,dim,P,diag,mats,gens,gal; fi; auts:=Concatenation(auts, List(mats,s->GroupGeneralMappingByImages(G,G,gens,List(gens,x-> - Image(hom,PreImagesRepresentative(hom,x)^s))))); + Image(hom,PreImagesRepresentativeNC(hom,x)^s))))); else gal:=Group(()); # to force trivial @@ -2179,13 +2179,13 @@ local d,id,H,iso,aut,auts,i,all,hom,field,dim,P,diag,mats,gens,gal; List(MinimalGeneratingSet(gal), s->GroupGeneralMappingByImages(G,G,gens,List(gens,x-> Image(hom, - List(PreImagesRepresentative(hom,x),r->List(r,y->Image(s,y)))))))); + List(PreImagesRepresentativeNC(hom,x),r->List(r,y->Image(s,y)))))))); fi; # graph if id.series="L" and id.parameter[1]>2 then Add(auts, GroupGeneralMappingByImages(G,G,gens,List(gens,x-> - Image(hom,Inverse(TransposedMat(PreImagesRepresentative(hom,x))))))); + Image(hom,Inverse(TransposedMat(PreImagesRepresentativeNC(hom,x))))))); all:=true; elif id.series="L" and id.parameter[1]=2 then # note no graph @@ -2350,7 +2350,7 @@ InstallGlobalFunction(AutomorphismGroupFittingFree,function(g) thom:=i[j][2]; thom:=GroupHomomorphismByImagesNC(t,t,GeneratorsOfGroup(t), List(GeneratorsOfGroup(t), - j->Image(thom,PreImagesRepresentative(thom,j)^gen))); + j->Image(thom,PreImagesRepresentativeNC(thom,j)^gen))); thom:=Image(auph,thom); Add(genimgs,thom); od; @@ -2408,7 +2408,7 @@ InstallGlobalFunction(AutomorphismGroupFittingFree,function(g) for i in gens do au:=GroupHomomorphismByImages(g,g,GeneratorsOfGroup(g), List(GeneratorsOfGroup(g), - j->PreImagesRepresentative(emb,Image(emb,j)^i))); + j->PreImagesRepresentativeNC(emb,Image(emb,j)^i))); Add(a,au); od; au:=Group(a); @@ -2449,7 +2449,7 @@ InstallGlobalFunction(AutomorphismGroupFittingFree,function(g) bi:=[]; for i in newbas do s:=List(stbs[i], - x->Image(emb,Image(autom,PreImagesRepresentative(emb,x)))); + x->Image(emb,Image(autom,PreImagesRepresentativeNC(emb,x)))); s:=First(orb[orpo[i]],x->ForAll(s,j->x^j=x)); Add(bi,s); od; diff --git a/lib/norad.gi b/lib/norad.gi index 7457f035e8..6323d1070d 100644 --- a/lib/norad.gi +++ b/lib/norad.gi @@ -173,7 +173,7 @@ local d,orb,len,S,depths,rel,stb,img,pos,i,j,k,ii,po,rep,sg,sf,sfs,fr,first, if r<>fail then Add(good,r);fi; return r<>fail; end); - good:=List(good,x->PreImagesRepresentative(pacthom,x)); + good:=List(good,x->PreImagesRepresentativeNC(pacthom,x)); good:=Filtered(good,x->not IsOne(x[2])); @@ -418,7 +418,7 @@ local sus,ser,len,factorhom,uf,n,d,up,mran,nran,mpcgs,pcgs,pcisom,nf,ng,np,sub, glact:=ActionHomomorphism(glperm,lvecs, GeneratorsOfGroup(glperm), List(GeneratorsOfGroup(glperm), - x->PreImagesRepresentative(glhom,x)), + x->PreImagesRepresentativeNC(glhom,x)), OnLines,"surjective"); stb:=Image(glact); for clu in localclust do @@ -478,7 +478,7 @@ local sus,ser,len,factorhom,uf,n,d,up,mran,nran,mpcgs,pcgs,pcisom,nf,ng,np,sub, Info(InfoFitFree,1,"Radsize= ",Size(ufr)," index ",Index(uf,ufr)); uff:=SmallGeneratingSet(uf); - ufg:=List(uff,x->PreImagesRepresentative(sus.rest,x)); + ufg:=List(uff,x->PreImagesRepresentativeNC(sus.rest,x)); n:=Normalizer(Image(factorhom),uf); @@ -503,7 +503,7 @@ local sus,ser,len,factorhom,uf,n,d,up,mran,nran,mpcgs,pcgs,pcisom,nf,ng,np,sub, nf:=SmallGeneratingSet(n); fi; - ng:=List(nf,x->PreImagesRepresentative(factorhom,x)); + ng:=List(nf,x->PreImagesRepresentativeNC(factorhom,x)); np:=pcgs; up:=sus.pcgs; diff --git a/lib/onecohom.gi b/lib/onecohom.gi index c2b6d29723..e1432730e3 100644 --- a/lib/onecohom.gi +++ b/lib/onecohom.gi @@ -128,7 +128,7 @@ local hom,fg,fpi,fpg,nt,fam; fpg:=FreeGeneratorsOfFpGroup(Range(hom)); ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(hom))]; ocr.generators:=List(GeneratorsOfGroup(Range(hom)), - i->PreImagesRepresentative(hom,i)); + i->PreImagesRepresentativeNC(hom,i)); else if (Index(ocr.group,nt)>Size(nt)^3 @@ -159,9 +159,9 @@ local hom,fg,fpi,fpg,nt,fam; fpg:=FreeGeneratorsOfFpGroup(Range(fpi)); ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(fpi)), List(GeneratorsOfGroup(Range(fpi)), - i->PreImagesRepresentative(fpi,i))]; + i->PreImagesRepresentativeNC(fpi,i))]; if not IsBound(ocr.generators) then - ocr.generators:=List(ocr.factorpres[3],i->PreImagesRepresentative(hom,i)); + ocr.generators:=List(ocr.factorpres[3],i->PreImagesRepresentativeNC(hom,i)); fi; @@ -171,7 +171,7 @@ local hom,fg,fpi,fpg,nt,fam; # else # old code # fpi:=IsomorphismFpGroup(ocr.group:noshort:=true); # ocr.generators:=List(MappingGeneratorsImages(fpi)[2], -# i->PreImagesRepresentative(fpi,i)); +# i->PreImagesRepresentativeNC(fpi,i)); # fi; fpg:=FreeGeneratorsOfFpGroup(Range(fpi)); ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(fpi))]; @@ -191,7 +191,7 @@ local hom,fg,fpi,fpg,nt,fam; fpi:=IsomorphismFpGroupByChiefSeriesFactor(ocr.group,"f",nt); fam:=FamilyObj(One(Range(fpi))); fpg:=FreeGeneratorsOfFpGroup(Range(fpi)); - ocr.generators:=List(fpg,i->PreImagesRepresentative(fpi, + ocr.generators:=List(fpg,i->PreImagesRepresentativeNC(fpi, ElementOfFpGroup(fam,i))); ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(fpi)),ocr.generators]; fi; diff --git a/lib/oprt.gi b/lib/oprt.gi index a7b758b73f..9d12954fef 100644 --- a/lib/oprt.gi +++ b/lib/oprt.gi @@ -2920,7 +2920,7 @@ local G, D, d, e, gens, acts, act, xset, hom, p, rep; rep := RepresentativeActionOp( ImagesSource( hom ), d, e, OnPoints ); if rep <> fail then - rep := PreImagesRepresentative( hom, rep ); + rep := PreImagesRepresentativeNC( hom, rep ); fi; return rep; elif IsBound( D ) then @@ -3374,9 +3374,9 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . build matrix +#M PreImagesRepresentativeNC( , ) . . . . . . . . . build matrix ## -InstallMethod( PreImagesRepresentative,"IsLinearActionHomomorphism", +InstallMethod( PreImagesRepresentativeNC,"IsLinearActionHomomorphism", FamRangeEqFamElm, [ IsLinearActionHomomorphism, IsPerm ], 0, function( hom, elm ) local V, G, Grep, filt, R, xset,lab,f; @@ -3388,7 +3388,7 @@ function( hom, elm ) TryNextMethod(); fi; - # PreImagesRepresentative does not test membership + # PreImagesRepresentativeNC does not test membership #if not elm in Image( hom ) then return fail; fi; xset:=UnderlyingExternalSet(hom); V := HomeEnumerator(xset); @@ -3420,7 +3420,7 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . build matrix +#M PreImagesRepresentativeNC( , ) . . . . . . . . . build matrix ## ## The idea is as follows. ## We have an $F$-basis $(v_1, \ldots, v_n)$. @@ -3441,7 +3441,7 @@ end ); ## matrix group contains all scalar matrices, or we know that the preimage ## has determinant $1$ and taking the root in question is unique. ## -InstallMethod( PreImagesRepresentative,"IsProjectiveActionHomomorphism", +InstallMethod( PreImagesRepresentativeNC,"IsProjectiveActionHomomorphism", FamRangeEqFamElm, [ IsProjectiveActionHomomorphism, IsPerm ], 0, function( hom, elm ) local V, G, Grep, filt, R, mat, xset,lab,dim,sol,i; @@ -3457,7 +3457,7 @@ function( hom, elm ) TryNextMethod(); fi; - # PreImagesRepresentative does not test membership + # PreImagesRepresentativeNC does not test membership #if not elm in Image( hom ) then return fail; fi; xset:=UnderlyingExternalSet(hom); V := HomeEnumerator(xset); diff --git a/lib/oprtglat.gi b/lib/oprtglat.gi index b80acc2755..43b4531805 100644 --- a/lib/oprtglat.gi +++ b/lib/oprtglat.gi @@ -224,7 +224,7 @@ local acts,gps,clusters,conj,ncl,nacts,i,j,new,q,hom,lhom,c,n,r,len, Info(InfoLattice,5,"reduced (factor) by ",Size(q)/Size(n)); Add(nacts,PreImage(lhom,n)); for k in new.clusters[j] do - r:=PreImagesRepresentative(lhom,new.conjugators[k]); + r:=PreImagesRepresentativeNC(lhom,new.conjugators[k]); conj[c[k]]:=conj[c[k]]*r; gps[c[k]]:=gps[c[k]]^r; od; diff --git a/lib/oprtperm.gi b/lib/oprtperm.gi index 0678e7eafb..a1a1616b7c 100644 --- a/lib/oprtperm.gi +++ b/lib/oprtperm.gi @@ -964,7 +964,7 @@ InstallMethod( Earns, "G, ints, gens, perms, act", true, fi; gens := [ ]; for gen in GeneratorsOfGroup( Centre( P ) ) do - pre := PreImagesRepresentative( f, gen ); + pre := PreImagesRepresentativeNC( f, gen ); ord := Order( pre ); pa := 1; while ord mod p = 0 do ord := ord / p; diff --git a/lib/pcgsnice.gi b/lib/pcgsnice.gi index 0496a0c212..caa90d90ec 100644 --- a/lib/pcgsnice.gi +++ b/lib/pcgsnice.gi @@ -23,7 +23,7 @@ AttributeMethodByNiceMonomorphism( Pcgs, if npcgs = fail then return fail; fi; - pcgs := List( npcgs, gen -> PreImagesRepresentative( nice, gen ) ); + pcgs := List( npcgs, gen -> PreImagesRepresentativeNC( nice, gen ) ); pcgs := PcgsByPcSequenceNC( ElementsFamily( FamilyObj( G ) ), pcgs ); if HasIsPrimeOrdersPcgs( npcgs ) and IsPrimeOrdersPcgs( npcgs ) then SetIsPrimeOrdersPcgs( pcgs, true ); diff --git a/lib/permdeco.gi b/lib/permdeco.gi index f57059f634..e605798c0f 100644 --- a/lib/permdeco.gi +++ b/lib/permdeco.gi @@ -314,7 +314,7 @@ local tryrep,sel,selin,a,s,dom,iso,stabs,outs,map,i,j,p,found,seln, for i in GeneratorsOfGroup(G) do a:=One(d); for j in [1..Length(stabs)] do - a:=a*Image(Embedding(d,j),PreImagesRepresentative(outs[j],i)); + a:=a*Image(Embedding(d,j),PreImagesRepresentativeNC(outs[j],i)); od; Add(p,a); od; @@ -360,7 +360,7 @@ local G,H,tg,th,hom, tga, Gemb, C, outs, auts, ar, Hemb; i->GroupHomomorphismByImagesNC(tg,tg, GeneratorsOfGroup(tg), List(GeneratorsOfGroup(tg), - j->Image(hom,PreImagesRepresentative(hom,j)^i)))); + j->Image(hom,PreImagesRepresentativeNC(hom,j)^i)))); Gemb:=fail; if ForAll(tga,IsConjugatorAutomorphism) then @@ -442,7 +442,7 @@ local cs,i,k,u,o,norm,T,Thom,autos,ng,a,Qhom,Q,Ehom,genimages, autos:=List(ng,i->GroupHomomorphismByImagesNC(T,T, GeneratorsOfGroup(T), List(GeneratorsOfGroup(T), - j->Image(Thom,PreImagesRepresentative(Thom,j)^i)))); + j->Image(Thom,PreImagesRepresentativeNC(Thom,j)^i)))); a:=AutomorphismRepresentingGroup(T,autos); Thom:=GroupHomomorphismByImagesNC(norm,a[1],ng,a[3]); a:=a[1]; @@ -455,7 +455,7 @@ local cs,i,k,u,o,norm,T,Thom,autos,ng,a,Qhom,Q,Ehom,genimages, # define isomorphisms between the components reps:=List([1..n],i-> - PreImagesRepresentative(Qhom,RepresentativeAction(Q,1,i))); + PreImagesRepresentativeNC(Qhom,RepresentativeAction(Q,1,i))); genimages:=[]; for i in GeneratorsOfGroup(G) do @@ -539,7 +539,7 @@ local limit, r, pcgs, ser, ind, m, p, l, l2, good, i, j,nser,hom; ser:=InvariantElementaryAbelianSeries(p, List( GeneratorsOfGroup( G ), i -> GroupHomomorphismByImagesNC(p,p,GeneratorsOfGroup(p), List(GeneratorsOfGroup(p), - j->Image(m,PreImagesRepresentative(m,j)^i)))), + j->Image(m,PreImagesRepresentativeNC(m,j)^i)))), TrivialSubgroup(p),true); ser:=List(ser,i->PreImage(m,i)); else diff --git a/lib/relation.gi b/lib/relation.gi index e5208df4b7..115e5409ae 100644 --- a/lib/relation.gi +++ b/lib/relation.gi @@ -71,7 +71,7 @@ ## ## I. Operations and methods for binary relations on points ## 1. ImagesElm (compatibility with GeneralMapping) -## 2. PreImagesElm (compatibility with GeneralMapping) +## 2. PreImagesElmNC (compatibility with GeneralMapping) ## 3. \=, \in, \< ## 4. \* for relations, transformations, and permutation ## 5. Set operations \+, \- (union, difference) @@ -92,7 +92,7 @@ ## 4. MeetEquivalenceRelations ## 5. \= ## 6. ImagesElm (compatibility with GeneralMapping) -## 7. PreImagesElm (compatibility with GeneralMapping) +## 7. PreImagesElmNC (compatibility with GeneralMapping) ## 8. PrintObj ## ## L. Constructors of equivalence classes @@ -104,7 +104,7 @@ ## 2. PrintObj, Enumerator ## 3. \< ## 4. ImagesRepresentative -## 6. PreImagesRepresentative +## 6. PreImagesRepresentativeNC ## ############################################################################ ############################################################################ @@ -230,7 +230,7 @@ InstallMethod(IsReflexiveBinaryRelation, ## #P IsSymmetricBinaryRelation() ## -## Depends on Images and Preimages returning SSorted lists. +## Depends on Images and PreimagesNC returning SSorted lists. ## InstallMethod(IsSymmetricBinaryRelation, @@ -250,7 +250,7 @@ InstallMethod(IsSymmetricBinaryRelation, List(Enumerator(UnderlyingRelation(m)),x->[x[1],x[2]]))); for e in el do - if not PreImages(m,e)=Images(m,e) then + if not PreImagesNC(m,e)=Images(m,e) then return false; fi; od; @@ -312,7 +312,7 @@ InstallMethod(IsAntisymmetricBinaryRelation, List(Enumerator(UnderlyingRelation(rel)),x->[x[1],x[2]]))); for e in el do - i := IntersectionSet(PreImages(rel,e),Images(rel,e)); + i := IntersectionSet(PreImagesNC(rel,e),Images(rel,e)); if not IsEmpty(i) and not i=[e] then return false; fi; @@ -376,7 +376,7 @@ function(rel) for a in Source(rel) do for b in Source(rel) do # intersecting downsets - intersection := Intersection(PreImages(rel,b),PreImages(rel,a)); + intersection := Intersection(PreImagesNC(rel,b),PreImagesNC(rel,a)); # new relation on the intersection induced by the original relation nrel := PartialOrderByOrderingFunction( Domain(intersection), @@ -607,11 +607,11 @@ InstallMethod(HasseDiagramBinaryRelation, HDBRMinElts := function(list, rel) ## x minimal if - ## {y in list | y<>x and y in PreImagesElm( rel,x)} is empty + ## {y in list | y<>x and y in PreImagesElmNC( rel,x)} is empty ## return Filtered(list, x->IsEmpty(Filtered(list, y-> (y <> x) and - (y in PreImagesElm(rel,x))))); + (y in PreImagesElmNC(rel,x))))); end; ## return the elements which cover x in rel @@ -983,11 +983,11 @@ InstallMethod(ImagesElm, ############################################################################# ## -#M PreImagesElm( , ) +#M PreImagesElmNC( , ) ## ## For binary relations over [1..n] represented as a list of images ## -InstallMethod(PreImagesElm, +InstallMethod(PreImagesElmNC, "for binary rels over [1..n] with images list", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep, IsPosInt], 0, function( rel, n ) @@ -1781,9 +1781,9 @@ InstallMethod( ImagesRepresentative, "equivalence relations", ############################################################################# ## -#M PreImagesRepresentative( , ) . . . for equivalence relations +#M PreImagesRepresentativeNC( , ) . . . for equivalence relations ## -InstallMethod( PreImagesRepresentative, "equivalence relations", +InstallMethod( PreImagesRepresentativeNC, "equivalence relations", FamRangeEqFamElm, [IsEquivalenceRelation, IsObject], 0, function( map, elm ) return elm; @@ -1813,9 +1813,9 @@ InstallMethod( ImagesElm, ############################################################################# ## -#M PreImagesElm( , ) for equivalence relations with partition +#M PreImagesElmNC( , ) . for equivalence relations with partition ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "equivalence relations with partition and element", FamRangeEqFamElm, [IsEquivalenceRelation and HasEquivalenceRelationPartition, diff --git a/lib/ringhom.gi b/lib/ringhom.gi index 21791f48a8..2dc8ab4bb7 100644 --- a/lib/ringhom.gi +++ b/lib/ringhom.gi @@ -444,9 +444,9 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . for ring g.m.b.i. +#M PreImagesRepresentativeNC( , ) . . . . . . for ring g.m.b.i. ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for ring g.m.b.i., and element", FamRangeEqFamElm, [ IsRingGeneralMapping and IsRingGeneralMappingByImagesDefaultRep, diff --git a/lib/schur.gi b/lib/schur.gi index f53b66dbdd..b34a4608c9 100644 --- a/lib/schur.gi +++ b/lib/schur.gi @@ -130,7 +130,7 @@ InstallMethod(EpimorphismSchurCover,"generic, via fp group",true,[IsGroup],1, j->One(F))))); hom:=GroupHomomorphismByImagesNC(D,G,GeneratorsOfGroup(D), - List(Dgens,i->PreImagesRepresentative(iso,i))); + List(Dgens,i->PreImagesRepresentativeNC(iso,i))); Dgens:=TzImagesOldGens(p); Dgens:=List(Dgens{[Length(Fgens)+1..Length(Dgens)]}, i->MappedWord(i,p!.generators,GeneratorsOfGroup(D))); @@ -201,7 +201,7 @@ local s,pcgs,n,l,cov,pco,ng,gens,imgs,ran,zer,i,j,e,a, fi; # get a decent pcgs for the cover - pco:=List(pcgs,i->Image(epi,PreImagesRepresentative(de,i))); + pco:=List(pcgs,i->Image(epi,PreImagesRepresentativeNC(de,i))); Append(pco,Pcgs(mul)); pco:=PcgsByPcSequenceNC(FamilyObj(One(cov)),pco); @@ -261,7 +261,7 @@ local s,pcgs,n,l,cov,pco,ng,gens,imgs,ran,zer,i,j,e,a, # factor generators gens:=GeneratorsOfGroup(qs); # their conjugates - imgs:=List(gens,j->PreImagesRepresentative(epi,Image(epi,j)^dc[i])); + imgs:=List(gens,j->PreImagesRepresentativeNC(epi,Image(epi,j)^dc[i])); rels:=ClosureGroup(rels,CommutGenImgs(pco,gens,imgs, Intersection(mul,DerivedSubgroup(qs)))); fi; @@ -306,7 +306,7 @@ BindGlobal("PositiveExponentsPresentationFpHom",function(hom) local G,F,geni,ro,fam,r,i,j,rel,n,e; G:=Image(hom); F:=FreeGeneratorsOfFpGroup(G); - geni:=List(GeneratorsOfGroup(G),i->PreImagesRepresentative(hom,i)); + geni:=List(GeneratorsOfGroup(G),i->PreImagesRepresentativeNC(hom,i)); ro:=List(geni,Order); fam:=FamilyObj(F[1]); r:=[]; @@ -351,7 +351,7 @@ local G,H,D,T,i,j,k,l,a,h,nk,evals,rels,gens,r,np,g,invlist,el,elp,TL,rp,pos; # this will guarantee we always take the same preimages el:=AsSSortedListNonstored(H); - elp:=List(el,i->PreImagesRepresentative(s,i)); + elp:=List(el,i->PreImagesRepresentativeNC(s,i)); #ensure the preimage of identity is one if IsOne(el[1]) then pos:=1; @@ -401,13 +401,13 @@ local G,H,D,T,i,j,k,l,a,h,nk,evals,rels,gens,r,np,g,invlist,el,elp,TL,rp,pos; fi; np:=k*g; nk:=TL[PositionCanonical(T,np)]; - #h:=h*PreImagesRepresentative(s,np/nk); + #h:=h*PreImagesRepresentativeNC(s,np/nk); h:=h*elp[Position(el,np/nk)]; k:=nk; od; - #Print(PreImagesRepresentative(s,Image(s,h))*h,"\n"); - #a:=a/PreImagesRepresentative(s,Image(s,h))*h; + #Print(PreImagesRepresentativeNC(s,Image(s,h))*h,"\n"); + #a:=a/PreImagesRepresentativeNC(s,Image(s,h))*h; a:=a/h*elp[Position(el,Image(s,h))]; od; @@ -485,7 +485,7 @@ local G,B,P,s,D,i,j,v,ri,rank,bas,basr,row,rel,sol,snf,mat; j:=NaturalHomomorphismByNormalSubgroupNC(D,v); i:=GeneratorsOfGroup(Image(j)); i:=GroupHomomorphismByImagesNC(Image(j),P,i, - List(i,k->ImageElm(s,PreImagesRepresentative(j,k)))); + List(i,k->ImageElm(s,PreImagesRepresentativeNC(j,k)))); SetKernelOfMultiplicativeGeneralMapping(i, Image(j,KernelOfMultiplicativeGeneralMapping(s))); return i; @@ -558,7 +558,7 @@ local hom, #isomorphism fp s:=sl[pp]; mg:=IsomorphismPermGroup(KernelOfMultiplicativeGeneralMapping(s)); mg:=List(IndependentGeneratorsOfAbelianGroup(Image(mg)), - i->PreImagesRepresentative(mg,i)); + i->PreImagesRepresentativeNC(mg,i)); sdc:=ListWithIdenticalEntries(Last(ngl),One(Source(s))); sdc{[ngl[pp]+1..ngl[pp+1]]}:=mg; @@ -579,7 +579,7 @@ local hom, #isomorphism fp q:=[]; for i in ce do - Add(q,PreImagesRepresentative(sdc,i[2])); + Add(q,PreImagesRepresentativeNC(sdc,i[2])); od; rel2[pp]:=q; od; diff --git a/lib/semirel.gi b/lib/semirel.gi index dd0fad38fa..f3bb8188cc 100644 --- a/lib/semirel.gi +++ b/lib/semirel.gi @@ -1299,7 +1299,7 @@ end); ######## ######## -InstallMethod(PreImagesRepresentative, "for semigroup homomorphism by images", +InstallMethod(PreImagesRepresentativeNC, "for semigroup homomorphism by images", FamRangeEqFamElm, [IsSemigroupHomomorphism and IsSemigroupHomomorphismByImagesRep, IsMultiplicativeElement], function(hom, x) diff --git a/lib/stbcbckt.gi b/lib/stbcbckt.gi index f0b4eb0046..1d9ccd727f 100644 --- a/lib/stbcbckt.gi +++ b/lib/stbcbckt.gi @@ -2602,7 +2602,7 @@ dom, et, ft, Pr, rbase, BF, Q, data,lc; found:=PartitionBacktrack( G, Pr, true, rbase, data, L, R ); if IsPerm(found) and map<>false then - found:=PreImagesRepresentative(map,found); + found:=PreImagesRepresentativeNC(map,found); fi; return found; end ); diff --git a/lib/twocohom.gi b/lib/twocohom.gi index 179e1f453a..7af0728b1e 100644 --- a/lib/twocohom.gi +++ b/lib/twocohom.gi @@ -813,7 +813,7 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, od; gens:=List(GeneratorsOfGroup(FamilyObj(fpg)!.wholeGroup), - x->PreImagesRepresentative(fp,x)); + x->PreImagesRepresentativeNC(fp,x)); hom:=GroupHomomorphismByImagesNC(G,Group(mo.generators), GeneratorsOfGroup(G),mo.generators); @@ -845,7 +845,7 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, else # Length of r[1] is 1. That is, this generator is not used! m:=First(RelationsOfFpMonoid(mon),x->List(x,LetterRepAssocWord)=r); - m:=List(m,x->PreImagesRepresentative(fm,ElementOfFpMonoid(FamilyObj(One(mon)),x))); + m:=List(m,x->PreImagesRepresentativeNC(fm,ElementOfFpMonoid(FamilyObj(One(mon)),x))); m:=List(m,UnderlyingElement); # free group elements/words if not IsOne(m[1]*Subword(m[2],1,1)) then @@ -866,7 +866,7 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, model:=ValueOption("model"); if model<>fail then q:=GQuotients(model,G)[1]; - pre:=List(gens,x->PreImagesRepresentative(q,x)); + pre:=List(gens,x->PreImagesRepresentativeNC(q,x)); ker:=KernelOfMultiplicativeGeneralMapping(q); pcgs:=Pcgs(ker); l1:=GModuleByMats(LinearActionLayer(Group(pre),pcgs),mo.field); @@ -880,7 +880,7 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, m:=GroupGeneralMappingByImagesNC(fpg,model,GeneratorsOfGroup(fpg),pre); mats:=List(GeneratorsOfMonoid(mon), x->ImagesRepresentative(m, - PreImagesRepresentative(fm,x))); #Elements for monoid generators + PreImagesRepresentativeNC(fm,x))); #Elements for monoid generators nonone:=[1..Length(mats)]; pre:=mats; onemat:=One(G); @@ -896,8 +896,8 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, zerovec:=Zero(onemat[1]); mats:=List(GeneratorsOfMonoid(mon), - x->ImagesRepresentative(hom,PreImagesRepresentative(fp, - PreImagesRepresentative(fm,x)))); # matrices for monoid generators + x->ImagesRepresentative(hom,PreImagesRepresentativeNC(fp, + PreImagesRepresentativeNC(fm,x)))); # matrices for monoid generators one:=One(mats[1]); nonone:=Filtered([1..Length(mats)],x->not IsOne(mats[x])); zero:=zerovec; @@ -1046,7 +1046,7 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, one:=One(FreeGroupOfFpGroup(fpg)); k:=List(GeneratorsOfMonoid(mon), - x->UnderlyingElement(PreImagesRepresentative(fm,x))); + x->UnderlyingElement(PreImagesRepresentativeNC(fm,x))); # matrix corresponding to monoid word mapped2:=function(list) local a,i; @@ -1124,8 +1124,8 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, local a; if not IsBound(imagemonwords[nr]) then # apply automorphism - a:=PreImagesRepresentative(fm,GeneratorsOfMonoid(mon)[nr]); - a:=PreImagesRepresentative(fp,a); + a:=PreImagesRepresentativeNC(fm,GeneratorsOfMonoid(mon)[nr]); + a:=PreImagesRepresentativeNC(fp,a); a:=ImagesRepresentative(autom,a); a:=ImagesRepresentative(fp,a); a:=ImagesRepresentative(fm,a); diff --git a/lib/vspchom.gi b/lib/vspchom.gi index 4b6aee7a75..daf0e145bf 100644 --- a/lib/vspchom.gi +++ b/lib/vspchom.gi @@ -485,9 +485,9 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . for left module g.m.b.i. +#M PreImagesRepresentativeNC( , ) . . . for left module g.m.b.i. ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for left module g.m.b.i., and element", FamRangeEqFamElm, [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, @@ -1221,9 +1221,9 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . for left module m.b.m. +#M PreImagesRepresentativeNC( , ) . . . . for left module m.b.m. ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for left module m.b.m., and element", FamRangeEqFamElm, [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, From 1f6bbafcbeb686978daeaf0db4edd4fc69da1927 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 20 May 2026 19:01:26 +0100 Subject: [PATCH 002/114] added non-NC methods so that tests pass --- lib/alghom.gi | 32 ++-- lib/alglie.gi | 14 ++ lib/field.gi | 25 +++ lib/fldabnum.gi | 35 ++++- lib/ghom.gi | 11 ++ lib/ghomfp.gi | 25 +++ lib/ghompcgs.gi | 11 ++ lib/ghomperm.gi | 11 ++ lib/gprdmat.gi | 35 +++++ lib/gprdperm.gi | 47 ++++++ lib/grpmat.gi | 12 ++ lib/grpnice.gi | 12 ++ lib/liefam.gi | 11 ++ lib/mapprep.gi | 222 ++++++++++++++++++++++++++- lib/mgmring.gi | 43 ++++++ lib/morpheus.gi | 10 ++ lib/oprt.gi | 20 +++ lib/relation.gi | 34 ++++ lib/ringhom.gi | 13 ++ lib/vspchom.gi | 24 +++ tst/testbugfix/2012-11-25-t00264.tst | 4 +- 21 files changed, 629 insertions(+), 22 deletions(-) diff --git a/lib/alghom.gi b/lib/alghom.gi index 550ac43fd6..51147d67cd 100644 --- a/lib/alghom.gi +++ b/lib/alghom.gi @@ -576,7 +576,8 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesRepresentativeNC( , ) . . . . . . for algebra g.m.b.i. +#M PreImagesRepresentativeNC( , ) . . . . . for algebra g.m.b.i. +#M PreImagesRepresentative( , ) . . . . . . for algebra g.m.b.i. ## InstallMethod( PreImagesRepresentativeNC, "for algebra g.m.b.i., and element", @@ -588,6 +589,18 @@ InstallMethod( PreImagesRepresentativeNC, AsLeftModuleGeneralMappingByImages(map), elm ); end ); +InstallMethod( PreImagesRepresentative, + "for algebra g.m.b.i., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsAlgebraGeneralMappingByImagesDefaultRep, + IsObject ], + function( map, elm ) + if not ( elm in Range( map ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); + ############################################################################# ## @@ -915,12 +928,6 @@ BindGlobal( "PreImagesRepresentativeOperationAlgebraHomomorphism", function( oph return mat; end ); -InstallMethod( PreImagesRepresentativeNC, - "for an operation algebra homomorphism, and an element", - FamRangeEqFamElm, - [ IsOperationAlgebraHomomorphismDefaultRep, IsMatrix ], - PreImagesRepresentativeOperationAlgebraHomomorphism ); - ############################################################################# ## @@ -1074,17 +1081,6 @@ InstallMethod( ImagesRepresentative, end ); -############################################################################# -## -#M PreImagesRepresentativeNC( , ) -## -InstallMethod( PreImagesRepresentativeNC, - "for an alg. hom. from f. p. algebra, and an element", - FamRangeEqFamElm, - [ IsAlgebraHomomorphismFromFpRep, IsMatrix ], - PreImagesRepresentativeOperationAlgebraHomomorphism ); - - ############################################################################# ## #M OperationAlgebraHomomorphism( , , ) diff --git a/lib/alglie.gi b/lib/alglie.gi index d3343f8fc4..d682f71459 100644 --- a/lib/alglie.gi +++ b/lib/alglie.gi @@ -4018,6 +4018,7 @@ InstallMethod( ImagesRepresentative, ########################################################################### ## #M PreImagesRepresentativeNC( f, x ) +#M PreImagesRepresentative( f, x ) ## InstallMethod( PreImagesRepresentativeNC, "for Fp to SCA mapping, and element", @@ -4095,6 +4096,19 @@ InstallMethod( PreImagesRepresentativeNC, end); +InstallMethod( PreImagesRepresentative, + "for Fp to SCA mapping, and element", + FamRangeEqFamElm, + [ IsFptoSCAMorphism, IsSCAlgebraObj ], 0, + + function( f, x ) + if not ( x in Range( f ) ) then + return fail; + fi; + return PreImagesRepresentative( f, x ); + +end ); + ############################################################################# ## #M Dimension( ) diff --git a/lib/field.gi b/lib/field.gi index a65dd50266..ff2e31c3ba 100644 --- a/lib/field.gi +++ b/lib/field.gi @@ -1316,6 +1316,7 @@ InstallMethod( ImagesSet, ############################################################################# ## #M PreImagesElmNC( , ) . . . . . . . . . . . . preimage of an elm +#M PreImagesElm( , ) . . . . . . . . . . . . . preimage of an elm ## InstallMethod( PreImagesElmNC, "for field homomorphism and element", @@ -1331,10 +1332,22 @@ InstallMethod( PreImagesElmNC, fi; end ); +InstallMethod( PreImagesElm, + "for field homomorphism and element", + FamRangeEqFamElm, + [ IsFieldHomomorphism, IsObject ], + function ( hom, elm ) + if not (elm in Range(hom)) then + return []; + fi; + return PreImagesElm( hom, elm ); + end ); ############################################################################# ## #M PreImagesSetNC +#M PreImagesSet +## InstallMethod( PreImagesSetNC, "for field homomorphism and field", CollFamRangeEqFamElms, @@ -1345,3 +1358,15 @@ InstallMethod( PreImagesSetNC, UseSubsetRelation( Source( hom ), elms ); return elms; end ); + +InstallMethod( PreImagesSet, + "for field homomorphism and field", + CollFamRangeEqFamElms, + [ IsFieldHomomorphism, IsField ], + function ( hom, elms ) + if not IsSubset( Range(hom), elms ) then + return []; + fi; + return PreImagesSet( hom, elms ); + end ); + diff --git a/lib/fldabnum.gi b/lib/fldabnum.gi index 6fb312be2d..6c5f22d030 100644 --- a/lib/fldabnum.gi +++ b/lib/fldabnum.gi @@ -1918,7 +1918,8 @@ InstallMethod( PreImageElm, ############################################################################# ## -#M PreImagesElmNC( , ) . . . . . . for autom. of ab. number fields +#M PreImagesElmNC( , ) . . . . . for autom. of ab. number fields +#M PreImagesElm( , ) . . . . . . for autom. of ab. number fields ## InstallMethod( PreImagesElmNC, "for ANF automorphism and scalar", @@ -1929,10 +1930,21 @@ InstallMethod( PreImagesElmNC, mod Conductor( Range( aut ) ) ) ]; end ); +InstallMethod( PreImagesElm, + "for ANF automorphism and scalar", + FamRangeEqFamElm, + [ IsFieldHomomorphism and IsANFAutomorphismRep, IsScalar ], + function ( aut, elm ) + if not ( elm in Range(aut) ) then + return []; + fi; + return PreImagesElmNC( aut, elm ); + end ); ############################################################################# ## #M PreImagesSetNC( , ) . . . . . for autom. of ab. number fields +#M PreImagesSet( , ) . . . . . . for autom. of ab. number fields ## InstallMethod( PreImagesSetNC, "for ANF automorphism and scalar", @@ -1942,10 +1954,21 @@ InstallMethod( PreImagesSetNC, return F; end ); +InstallMethod( PreImagesSet, + "for ANF automorphism and scalar", + CollFamRangeEqFamElms, + [ IsFieldHomomorphism and IsANFAutomorphismRep, IsField ], + function ( aut, F ) + if not IsSubset( Range(aut), F ) then + return []; + fi; + return PreImagesSetNC( aut, F ); + end ); ############################################################################# ## #M PreImagesRepresentativeNC( , ) for autom. of ab. number fields +#M PreImagesRepresentative( , ) . for autom. of ab. number fields ## InstallMethod( PreImagesRepresentativeNC, "for ANF automorphism and scalar", @@ -1956,6 +1979,16 @@ InstallMethod( PreImagesRepresentativeNC, mod Conductor( Range( aut ) ) ); end ); +InstallMethod( PreImagesRepresentative, + "for ANF automorphism and scalar", + FamRangeEqFamElm, + [ IsFieldHomomorphism and IsANFAutomorphismRep, IsScalar ], + function ( aut, elm ) + if not ( elm in Range( aut ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( aut, elm ); + end ); ############################################################################# ## diff --git a/lib/ghom.gi b/lib/ghom.gi index 8047a39206..29caa4a36b 100644 --- a/lib/ghom.gi +++ b/lib/ghom.gi @@ -254,6 +254,7 @@ end ); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . . . . . via images +#M PreImagesRepresentative( , ) . . . . . . . . . . . via images InstallMethod( PreImagesRepresentativeNC, "for PBG-Hom", FamRangeEqFamElm, [ IsPreimagesByAsGroupGeneralMappingByImages, @@ -268,6 +269,16 @@ function( hom, elm ) fi; end ); +InstallMethod( PreImagesRepresentative, "for PBG-Hom", FamRangeEqFamElm, + [ IsPreimagesByAsGroupGeneralMappingByImages, + IsMultiplicativeElementWithInverse ], 0, +function( hom, elm ) + if not ( elm in Range( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); + InstallAttributeMethodByGroupGeneralMappingByImages( CoKernelOfMultiplicativeGeneralMapping ); InstallAttributeMethodByGroupGeneralMappingByImages( KernelOfMultiplicativeGeneralMapping ); InstallAttributeMethodByGroupGeneralMappingByImages( PreImagesRange ); diff --git a/lib/ghomfp.gi b/lib/ghomfp.gi index fb2ce5f073..be891d7ee9 100644 --- a/lib/ghomfp.gi +++ b/lib/ghomfp.gi @@ -528,6 +528,7 @@ end); ############################################################################# ## #M PreImagesSetNC( , ) +#M PreImagesSet( , ) ## InstallMethod( PreImagesSetNC, "map from (sub)group of fp group", CollFamRangeEqFamElms, @@ -624,6 +625,16 @@ local s,gens,t,p,w,c,q,chom,tg,thom,hi,i,lp,max; return SubgroupOfWholeGroupByQuotientSubgroup(FamilyObj(s),u,Stabilizer(u,1)); end); +InstallMethod( PreImagesSet, "map from (sub)group of fp group", + CollFamRangeEqFamElms, + [ IsFromFpGroupHomomorphism,IsGroup ],0, +function(hom,u) + if not (u in Range(hom)) then + return []; + fi; + return PreImagesSetNC(hom,u); +end); + ############################################################################# ## @@ -719,6 +730,7 @@ end); ############################################################################# ## #M PreImagesRepresentativeNC +#M PreImagesRepresentative ## InstallMethod( PreImagesRepresentativeNC, "hom. to standard generators of fp group, using 'MappedWord'", @@ -747,6 +759,19 @@ local mapi; return mapi; end); +InstallMethod( PreImagesRepresentative, + "hom. to standard generators of fp group, using 'MappedWord'", + FamRangeEqFamElm, + [IsToFpGroupHomomorphismByImages,IsMultiplicativeElementWithInverse], + 1, +function(hom,elm) + if not (elm in Range(hom)) then + return fail; + fi; + return PreImagesRepresentativeNC(hom,elm); +end); + + ############################################################################# ## ## methods to construct homomorphisms to fp groups diff --git a/lib/ghompcgs.gi b/lib/ghompcgs.gi index 78ba75b339..984f80f3f3 100644 --- a/lib/ghompcgs.gi +++ b/lib/ghompcgs.gi @@ -504,6 +504,7 @@ end); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . . . . . via images +#M PreImagesRepresentative( , ) . . . . . . . . . . . via images ## InstallMethod( PreImagesRepresentativeNC, "method for pcgs hom", FamRangeEqFamElm, @@ -530,6 +531,16 @@ function( hom, elm ) return pre; end); +InstallMethod( PreImagesRepresentative, "method for pcgs hom", + FamRangeEqFamElm, + [ IsToPcGroupHomomorphismByImages,IsMultiplicativeElementWithInverse ], 0, +function( hom, elm ) + if not ( elm in Range( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); + ############################################################################# ## #M NaturalHomomorphismByNormalSubgroup( , ) . . . . . . for pc groups diff --git a/lib/ghomperm.gi b/lib/ghomperm.gi index 7bf4a40a70..8b5c6a79dd 100644 --- a/lib/ghomperm.gi +++ b/lib/ghomperm.gi @@ -1163,6 +1163,7 @@ end); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . for perm group range +#M PreImagesRepresentative( , ) . . . . . . for perm group range ## InstallMethod( PreImagesRepresentativeNC, FamRangeEqFamElm, [ IsToPermGroupGeneralMappingByImages, @@ -1171,6 +1172,16 @@ InstallMethod( PreImagesRepresentativeNC, FamRangeEqFamElm, return ImagesRepresentative( RestrictedInverseGeneralMapping( hom ), elm ); end ); +InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, + [ IsToPermGroupGeneralMappingByImages, + IsMultiplicativeElementWithInverse ], 0, + function( hom, elm ) + if not ( elm in Range( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); + ############################################################################# ## #F StabChainPermGroupToPermGroupGeneralMappingByImages( ) . . . local diff --git a/lib/gprdmat.gi b/lib/gprdmat.gi index c582173350..d73b63e568 100644 --- a/lib/gprdmat.gi +++ b/lib/gprdmat.gi @@ -144,6 +144,7 @@ end); ############################################################################# ## #M PreImagesRepresentativeNC(,) . . . . . . . . . . . of embedding +#M PreImagesRepresentative(,) . . . . . . . . . . . . of embedding ## InstallMethod(PreImagesRepresentativeNC,"matrix direct product embedding", FamRangeEqFamElm, @@ -162,6 +163,17 @@ local info,a,b; fi; end); +InstallMethod(PreImagesRepresentative,"matrix direct product embedding", + FamRangeEqFamElm, + [ IsEmbeddingDirectProductMatrixGroup, + IsMultiplicativeElementWithInverse ], +function(emb,g) + if not (g in Range(emb)) then + return fail; + fi; + return PreImagesRepresentativeNC(emb,g); +end); + ############################################################################# ## #R IsProjectionDirectProductMatrixGroup() projection onto direct factor @@ -207,6 +219,7 @@ end); ############################################################################# ## #M PreImagesRepresentativeNC(,) . . . . . . . . . . . of projection +#M PreImagesRepresentative(,) . . . . . . . . . . . . of projection ## InstallMethod(PreImagesRepresentativeNC,"matrix direct product projection", FamRangeEqFamElm, @@ -220,6 +233,17 @@ local info,a; return ImmutableMatrix(info.field,a); end); +InstallMethod(PreImagesRepresentative,"matrix direct product projection", + FamRangeEqFamElm, + [ IsProjectionDirectProductMatrixGroup, + IsMultiplicativeElementWithInverse ],0, +function(prj,m) + if not (m in Range(prj)) then + return fail; + fi; + return PreImagesRepresentativeNC(prj,m); +end); + ############################################################################# ## #M KernelOfMultiplicativeGeneralMapping() . . . . . . . of projection @@ -383,6 +407,7 @@ end); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . . . . . of embedding +#M PreImagesRepresentative( , ) . . . . . . . . . . . of embedding ## InstallMethod( PreImagesRepresentativeNC, "imprim matrix wreath product embedding", FamRangeEqFamElm, @@ -401,6 +426,16 @@ local info,a,b; fi; end); +InstallMethod( PreImagesRepresentative, + "imprim matrix wreath product embedding", FamRangeEqFamElm, + [ IsEmbeddingImprimitiveWreathProductMatrixGroup, + IsMultiplicativeElementWithInverse ], 0, +function( emb, g ) + if not (g in Range(emb)) then + return fail; + fi; + return PreImagesRepresentativeNC(emb,g); +end); ############################################################################# ## diff --git a/lib/gprdperm.gi b/lib/gprdperm.gi index 36973b6b46..75583f7a0d 100644 --- a/lib/gprdperm.gi +++ b/lib/gprdperm.gi @@ -170,6 +170,7 @@ end ); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . . . . . of embedding +#M PreImagesRepresentative( , ) . . . . . . . . . . . of embedding ## InstallMethod( PreImagesRepresentativeNC, "perm direct product embedding", FamRangeEqFamElm, @@ -191,6 +192,17 @@ InstallMethod( PreImagesRepresentativeNC, "perm direct product embedding", fi; end ); +InstallMethod( PreImagesRepresentative, "perm direct product embedding", + FamRangeEqFamElm, + [ IsEmbeddingDirectProductPermGroup, + IsMultiplicativeElementWithInverse ], + function( emb, g ) + if not ( g in Range( emb ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( emb, g ); +end ); + ############################################################################# ## #M ImagesSource( ) . . . . . . . . . . . . . . . . . . . of embedding @@ -293,6 +305,7 @@ end ); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . . . . . of projection +#M PreImagesRepresentative( , ) . . . . . . . . . . . of projection ## InstallMethod( PreImagesRepresentativeNC,"perm direct product projection", FamRangeEqFamElm, @@ -302,6 +315,17 @@ InstallMethod( PreImagesRepresentativeNC,"perm direct product projection", return g ^ DirectProductInfo( Source( prj ) ).perms[ prj!.component ]; end ); +InstallMethod( PreImagesRepresentative,"perm direct product projection", + FamRangeEqFamElm, + [ IsProjectionDirectProductPermGroup, + IsMultiplicativeElementWithInverse ], 0, + function( prj, g ) + if not ( g in Range( prj ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( prj, g ); +end ); + ############################################################################# ## #M KernelOfMultiplicativeGeneralMapping( ) . . . . . . . of projection @@ -467,6 +491,7 @@ end ); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . . . . . of projection +#M PreImagesRepresentative( , ) . . . . . . . . . . . of projection ## InstallMethod( PreImagesRepresentativeNC,"perm subdirect product projection", FamRangeEqFamElm, @@ -498,6 +523,17 @@ InstallMethod( PreImagesRepresentativeNC,"perm subdirect product projection", return elm; end ); +InstallMethod( PreImagesRepresentative,"perm subdirect product projection", + FamRangeEqFamElm, + [ IsProjectionSubdirectProductPermGroup, + IsMultiplicativeElementWithInverse ], 0, + function( prj, img ) + if not ( img in Range( prj ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( prj, img ); +end ); + ############################################################################# ## #M KernelOfMultiplicativeGeneralMapping( ) . . . . . . . of projection @@ -800,6 +836,7 @@ end ); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . . . . . of embedding +#M PreImagesRepresentative( , ) . . . . . . . . . . . of embedding ## InstallMethod( PreImagesRepresentativeNC, "imprim perm wreath product embedding", FamRangeEqFamElm, @@ -820,6 +857,16 @@ InstallMethod( PreImagesRepresentativeNC, ^ (info.perms[ emb!.component ] ^ -1); end ); +InstallMethod( PreImagesRepresentative, + "imprim perm wreath product embedding", FamRangeEqFamElm, + [ IsEmbeddingImprimitiveWreathProductPermGroup, + IsMultiplicativeElementWithInverse ], 0, + function( emb, g ) + if not ( g in Range( emb ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( emb, g ); +end ); ############################################################################# ## diff --git a/lib/grpmat.gi b/lib/grpmat.gi index 17eae4f5e0..65104b3aa4 100644 --- a/lib/grpmat.gi +++ b/lib/grpmat.gi @@ -1203,6 +1203,7 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . for a blow up isomorphism +#M PreImagesRepresentative( , ) . . . . for a blow up isomorphism ## InstallMethod( PreImagesRepresentativeNC, "for a blow up isomorphism, and a matrix in the range", @@ -1257,6 +1258,17 @@ InstallMethod( PreImagesRepresentativeNC, return preim; end ); +InstallMethod( PreImagesRepresentative, + "for a blow up isomorphism, and a matrix in the range", + FamRangeEqFamElm, + [ IsBlowUpIsomorphism, IsMatrix ], + function( iso, mat ) + if not ( mat in Range(iso) ) then + return fail; + fi; + return PreImagesRepresentativeNC( iso, mat ); + end ); + ############################################################################# ## diff --git a/lib/grpnice.gi b/lib/grpnice.gi index 6e3db2bd6f..25f7d78045 100644 --- a/lib/grpnice.gi +++ b/lib/grpnice.gi @@ -973,6 +973,7 @@ end); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . . . . . via images +#M PreImagesRepresentative( , ) . . . . . . . . . . . via images ## InstallMethod( PreImagesRepresentativeNC, "for PBG-Niceo", FamRangeEqFamElm, @@ -988,6 +989,17 @@ local p, tmp; return p; end ); +InstallMethod( PreImagesRepresentative, "for PBG-Niceo", + FamRangeEqFamElm, + [ IsPreimagesByAsGroupGeneralMappingByImages and IsNiceMonomorphism, + IsMultiplicativeElementWithInverse ], 0, +function( hom, elm ) + if not ( elm in Range(hom) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); + ############################################################################# ## #M NiceMonomorphism( ) . . diff --git a/lib/liefam.gi b/lib/liefam.gi index ca6c3161c6..0a5590b03d 100644 --- a/lib/liefam.gi +++ b/lib/liefam.gi @@ -456,6 +456,17 @@ InstallMethod( PreImagesElmNC, return [ elm![1] ]; end ); +InstallMethod( PreImagesElm, + "for Lie embedding and Lie object in default representation", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLieEmbeddingRep, + IsLieObject and IsPackedElementDefaultRep ], 0, + function( emb, elm ) + if not ( elm in Range(emb) ) then + return []; + fi; + return PreImagesElm( emb, elm ); + end ); ############################################################################# ## diff --git a/lib/mapprep.gi b/lib/mapprep.gi index 67ea3b1233..8b3ebe6fc2 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -303,6 +303,7 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## #M PreImagesElmNC( , ) . . . . . . . . . for composition mapping +#M PreImagesElm( , ) . . . . . . . . . . for composition mapping ## InstallMethod( PreImagesElmNC, "for a composition mapping, and an element", @@ -318,10 +319,22 @@ InstallMethod( PreImagesElmNC, fi; end ); +InstallMethod( PreImagesElm, + "for a composition mapping, and an element", + FamRangeEqFamElm, + [ IsCompositionMappingRep, IsObject ], 0, + function( com, elm ) + if not ( elm in Range(com) ) then + return []; + fi; + return PreImagesElmNC( com, elm ); + end ); + ############################################################################# ## #M PreImagesSetNC( , ) . . . . . . . . . for composition mapping +#M PreImagesSet( , ) . . . . . . . . . . for composition mapping ## InstallMethod( PreImagesSetNC, "for a composition mapping, and a collection", @@ -337,10 +350,22 @@ InstallMethod( PreImagesSetNC, fi; end ); +InstallMethod( PreImagesSet, + "for a composition mapping, and a collection", + CollFamRangeEqFamElms, + [ IsCompositionMappingRep, IsCollection ], 0, + function( com, elms ) + if not IsSubset( Range(com), elms ) then + return []; + fi; + return PreImagesSetNC( com, elms ); + end ); + ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . for composition mapping +#M PreImagesRepresentative( , ) . . . . . for composition mapping ## InstallMethod( PreImagesRepresentativeNC, "for a composition mapping, and an element", @@ -369,6 +394,17 @@ InstallMethod( PreImagesRepresentativeNC, fi; end ); +InstallMethod( PreImagesRepresentative, + "for a composition mapping, and an element", + FamRangeEqFamElm, + [ IsCompositionMappingRep, IsObject ], 0, + function( com, elm ) + if not ( elm in Range(com) ) then + return fail; + fi; + return PreImagesRepresentativeNC( com, elm ); + end ); + ############################################################################# ## @@ -629,7 +665,8 @@ end ); ############################################################################# ## -#M PreImagesRepresentativeNC( , ) . . . . . for mapping by function +#M PreImagesRepresentativeNC( , ) . . . . for mapping by function +#M PreImagesRepresentative( , ) . . . . . for mapping by function ## InstallMethod( PreImagesRepresentativeNC, "for mapping by function", @@ -643,6 +680,17 @@ InstallMethod( PreImagesRepresentativeNC, return map!.prefun( elm ); end ); +InstallMethod( PreImagesRepresentative, + "for mapping by function", + FamRangeEqFamElm, + [ IsMappingByFunctionRep, IsObject ], 0, + function ( map, elm ) + if not ( elm in Range(map) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); + ############################################################################# ## @@ -660,6 +708,7 @@ InstallMethod( PreImageElm, ############################################################################# ## #M PreImagesElmNC( , ) . . . . . . . . . . for mapping by function +#M PreImagesElm( , ) . . . . . . . . . . . for mapping by function ## InstallMethod( PreImagesElmNC, "for mapping by function", @@ -669,9 +718,22 @@ InstallMethod( PreImagesElmNC, return [ map!.invFun( elm ) ]; end ); +InstallMethod( PreImagesElm, + "for mapping by function", + FamRangeEqFamElm, + [ IsMappingByFunctionWithInverseRep, IsObject ], 0, + function ( map, elm ) + if not ( elm in Range(map) ) then + return []; + fi; + return PreImagesElmNC( map, elm ); + end ); + + ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . for mapping by function +#M PreImagesRepresentative( , ) . . . . . for mapping by function ## InstallMethod( PreImagesRepresentativeNC, "for mapping by function with inverse", @@ -681,6 +743,16 @@ InstallMethod( PreImagesRepresentativeNC, return map!.invFun( elm ); end ); +InstallMethod( PreImagesRepresentative, + "for mapping by function with inverse", + FamRangeEqFamElm, + [ IsMappingByFunctionWithInverseRep, IsObject ], 0, + function ( map, elm ) + if not ( elm in Range(map) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); ############################################################################# @@ -1055,6 +1127,7 @@ InstallMethod( PreImageElm, ############################################################################# ## #M PreImagesElmNC( , ) . . . . for inverse mapping and element +#M PreImagesElm( , ) . . . . . for inverse mapping and element ## InstallMethod( PreImagesElmNC, "for an inverse mapping and an element", @@ -1064,10 +1137,22 @@ InstallMethod( PreImagesElmNC, return ImagesElm( InverseGeneralMapping( inv ), elm ); end ); +InstallMethod( PreImagesElm, + "for an inverse mapping and an element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsInverseGeneralMappingRep, IsObject ], 0, + function ( inv, elm ) + if not ( elm in Range(inv) ) then + return []; + fi; + return PreImagesElmNC( inv, elm ); + end ); + ############################################################################# ## #M PreImagesSetNC( , ) . . for inverse mapping and collection +#M PreImagesSet( , ) . . . for inverse mapping and collection ## InstallMethod( PreImagesSetNC, "for an inverse mapping and a collection", @@ -1077,10 +1162,22 @@ InstallMethod( PreImagesSetNC, return ImagesSet( InverseGeneralMapping( inv ), elms ); end ); +InstallMethod( PreImagesSet, + "for an inverse mapping and a collection", + CollFamRangeEqFamElms, + [ IsGeneralMapping and IsInverseGeneralMappingRep, IsCollection ], 0, + function ( inv, elms ) + if not IsSubset( Range(inv), elms ) then + return []; + fi; + return PreImagesSetNC( inv, elms ); + end ); + ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . for inv. mapping and elm. +#M PreImagesRepresentative( , ) . . . for inv. mapping and elm. ## InstallMethod( PreImagesRepresentativeNC, "for an inverse mapping and an element", @@ -1090,6 +1187,17 @@ InstallMethod( PreImagesRepresentativeNC, return ImagesRepresentative( InverseGeneralMapping( inv ), elm ); end ); +InstallMethod( PreImagesRepresentative, + "for an inverse mapping and an element", + FamRangeEqFamElm, + [ IsInverseGeneralMappingRep, IsObject ], 0, + function ( inv, elm ) + if not ( elm in Range(inv) ) then + return fail; + fi; + return PreImagesRepresentativeNC( inv, elm ); + end ); + ############################################################################# ## @@ -1294,6 +1402,7 @@ InstallMethod( PreImageElm, ############################################################################# ## #M PreImagesElmMC( , ) . . . for identity mapping and element +#M PreImagesElm( , ) . . . . for identity mapping and element ## InstallMethod( PreImagesElmNC, "for identity mapping and object", @@ -1304,10 +1413,23 @@ InstallMethod( PreImagesElmNC, return [ elm ]; end ); +InstallMethod( PreImagesElm, + "for identity mapping and object", + FamRangeEqFamElm, + [ IsGeneralMapping and IsOne, IsObject ], + SUM_FLAGS, # can't do better + function ( id, elm ) + if not ( elm in Range(id) ) then + return []; + fi; + return PreImagesElmNC( id, elm ); + end ); + ############################################################################# ## #M PreImagesSetNC( , ) . . for identity mapping and collection +#M PreImagesSet( , ) . . . for identity mapping and collection ## InstallMethod( PreImagesSetNC, "for identity mapping and collection", @@ -1318,10 +1440,23 @@ InstallMethod( PreImagesSetNC, return elms; end ); +InstallMethod( PreImagesSet, + "for identity mapping and collection", + CollFamRangeEqFamElms, + [ IsGeneralMapping and IsOne, IsCollection ], + SUM_FLAGS, # can't do better + function ( id, elms ) + if not IsSubset( Range(id), elms ) then + return []; + fi; + return PreImagesSetNC( id, elms ); + end ); + ############################################################################# ## #M PreImagesRepresentativeNC( , ) +#M PreImagesRepresentative( , ) ## InstallMethod( PreImagesRepresentativeNC, "for identity mapping and object", @@ -1332,6 +1467,17 @@ InstallMethod( PreImagesRepresentativeNC, return elm; end ); +InstallMethod( PreImagesRepresentative, + "for identity mapping and object", + FamRangeEqFamElm, + [ IsGeneralMapping and IsOne, IsObject ], + SUM_FLAGS, # can't do better + function ( id, elm ) + if not ( elm in Range(id) ) then + return fail; + fi; + return elm; + end ); ############################################################################# ## @@ -1582,6 +1728,7 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## #M PreImagesElmNC( , ) . . . . for zero mapping and element +#M PreImagesElm( , ) . . . . . for zero mapping and element ## InstallMethod( PreImagesElmNC, "for zero mapping and object", @@ -1595,10 +1742,22 @@ InstallMethod( PreImagesElmNC, fi; end ); +InstallMethod( PreImagesElm, + "for zero mapping and object", + FamRangeEqFamElm, + [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS, + function( zero, elm ) + if not ( elm in Range(zero) ) then + return []; + fi; + return PreImagesElmNC( zero, elm ); + end ); + ############################################################################# ## #M PreImagesSetNC( , ) . . . for zero mapping and collection +#M PreImagesSet( , ) . . . . for zero mapping and collection ## InstallMethod( PreImagesSetNC, "for zero mapping and collection", @@ -1612,10 +1771,22 @@ InstallMethod( PreImagesSetNC, fi; end ); +InstallMethod( PreImagesSet, + "for zero mapping and collection", + CollFamRangeEqFamElms, + [ IsGeneralMapping and IsZero, IsCollection ], SUM_FLAGS, + function( zero, elms ) + if not IsSubset( Range(zero), elms ) then + return []; + fi; + return PreImagesSetNC( zero, elms ); + end ); + ############################################################################# ## #M PreImagesRepresentativeNC( , ) +#M PreImagesRepresentative( , ) ## InstallMethod( PreImagesRepresentativeNC, "for zero mapping and object", @@ -1629,6 +1800,17 @@ InstallMethod( PreImagesRepresentativeNC, fi; end ); +InstallMethod( PreImagesRepresentative, + "for zero mapping and object", + FamRangeEqFamElm, + [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS, + function( zero, elm ) + if not ( elm in Range(zero) ) then + return fail; + fi; + return PreImagesRepresentativeNC( zero, elm ); + end ); + ############################################################################# ## @@ -1818,6 +2000,7 @@ end ); ############################################################################# ## #M PreImagesElmNC( , ) . . . . . . . . . for restricted mapping +#M PreImagesElm( , ) . . . . . . . . . . for restricted mapping ## InstallMethod( PreImagesElmNC, "for a restricted mapping, and an element", @@ -1831,12 +2014,24 @@ InstallMethod( PreImagesElmNC, preim:=Intersection(Source(res),preim); fi; return preim; -end ); + end ); + +InstallMethod( PreImagesElm, + "for a restricted mapping, and an element", + FamRangeEqFamElm, + [ IsGeneralRestrictedMappingRep, IsObject ], 0, + function( res, elm ) + if not ( elm in Range(res) ) then + return []; + fi; + return PreImagesElmNC( res, elm ); + end ); ############################################################################# ## #M PreImagesSetNC( , ) . . . . . . . . . for restricted mapping +#M PreImagesSet( , ) . . . . . . . . . . for restricted mapping ## InstallMethod( PreImagesSetNC, "for a restricted mapping, and a collection", @@ -1852,10 +2047,22 @@ InstallMethod( PreImagesSetNC, return preim; end ); +InstallMethod( PreImagesSet, + "for a restricted mapping, and a collection", + CollFamRangeEqFamElms, + [ IsGeneralRestrictedMappingRep, IsCollection ], 0, + function( res, elms ) + if not IsSubset( Range(res), elms ) then + return []; + fi; + return PreImagesSetNC( res, elms ); + end ); + ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . for restricted mapping +#M PreImagesRepresentative( , ) . . . . . for restricted mapping ## InstallMethod( PreImagesRepresentativeNC, "for a restricted mapping, and an element", @@ -1877,6 +2084,17 @@ InstallMethod( PreImagesRepresentativeNC, fi; end ); +InstallMethod( PreImagesRepresentative, + "for a restricted mapping, and an element", + FamRangeEqFamElm, + [ IsGeneralRestrictedMappingRep, IsObject ], 0, + function( res, elm ) + if not ( elm in Range(res) ) then + return fail; + fi; + return PreImagesRepresentativeNC( res, elm ); + end ); + ############################################################################# ## diff --git a/lib/mgmring.gi b/lib/mgmring.gi index f7a4688a36..d4d0771b79 100644 --- a/lib/mgmring.gi +++ b/lib/mgmring.gi @@ -1236,6 +1236,17 @@ InstallMethod( PreImagesElmNC, fi; end ); +InstallMethod( PreImagesElm, + "for embedding of ring into magma ring, and free magma ring element", + FamRangeEqFamElm, + [ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ], + function ( emb, elm ) + if not ( elm in Range( emb ) ) then + return fail; + fi; + return PreImagesElm( emb, elm ); + end ); + InstallMethod( PreImagesRepresentativeNC, "for embedding of ring into magma ring, and free magma ring element", FamRangeEqFamElm, @@ -1252,6 +1263,17 @@ InstallMethod( PreImagesRepresentativeNC, fi; end ); +InstallMethod( PreImagesRepresentative, + "for embedding of ring into magma ring, and free magma ring element", + FamRangeEqFamElm, + [ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ], + function ( emb, elm ) + if not ( elm in Range( emb ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( emb, elm ); + end ); + ############################################################################# ## @@ -1340,6 +1362,17 @@ InstallMethod( PreImagesElmNC, fi; end ); +InstallMethod( PreImagesElm, + "for embedding of magma into magma ring, and free magma ring element", + FamRangeEqFamElm, + [ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ], + function ( emb, elm ) + if not ( elm in Range( emb ) ) then + return fail; + fi; + return PreImagesElmNC( emb, elm ); + end ); + InstallMethod( PreImagesRepresentativeNC, "for embedding of magma into magma ring, and free magma ring element", FamRangeEqFamElm, @@ -1356,6 +1389,16 @@ InstallMethod( PreImagesRepresentativeNC, fi; end ); +InstallMethod( PreImagesRepresentative, + "for embedding of magma into magma ring, and free magma ring element", + FamRangeEqFamElm, + [ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ], + function ( emb, elm ) + if not ( elm in Range( emb ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( emb, elm ); + end ); ############################################################################# ## diff --git a/lib/morpheus.gi b/lib/morpheus.gi index 9cb2957e14..a440d864fc 100644 --- a/lib/morpheus.gi +++ b/lib/morpheus.gi @@ -1071,6 +1071,7 @@ end); ############################################################################# ## #M PreImagesRepresentativeNC for OpHomAutomGrp +#M PreImagesRepresentative. for OpHomAutomGrp ## InstallMethod(PreImagesRepresentativeNC,"AutomGroup Niceomorphism", FamRangeEqFamElm,[IsActionHomomorphismAutomGroup,IsPerm],0, @@ -1086,6 +1087,15 @@ local xset,g,imgs; return elm; end); +InstallMethod(PreImagesRepresentative,"AutomGroup Niceomorphism", + FamRangeEqFamElm,[IsActionHomomorphismAutomGroup,IsPerm],0, +function(hom,elm) + if not (elm in Range(hom)) then + return fail; + fi; + return PreImagesRepresentativeNC(hom,elm); +end); + ############################################################################# ## diff --git a/lib/oprt.gi b/lib/oprt.gi index 9d12954fef..2a36087133 100644 --- a/lib/oprt.gi +++ b/lib/oprt.gi @@ -3375,6 +3375,7 @@ end ); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . . . . build matrix +#M PreImagesRepresentative( , ) . . . . . . . . . . build matrix ## InstallMethod( PreImagesRepresentativeNC,"IsLinearActionHomomorphism", FamRangeEqFamElm, [ IsLinearActionHomomorphism, IsPerm ], 0, @@ -3418,9 +3419,19 @@ function( hom, elm ) return hom!.linActInverse*elm; end ); +InstallMethod( PreImagesRepresentative,"IsLinearActionHomomorphism", + FamRangeEqFamElm, [ IsLinearActionHomomorphism, IsPerm ], 0, +function( hom, elm ) + if not ( elm in Range( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); + ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . . . . build matrix +#M PreImagesRepresentative( , ) . . . . . . . . . . build matrix ## ## The idea is as follows. ## We have an $F$-basis $(v_1, \ldots, v_n)$. @@ -3493,6 +3504,15 @@ function( hom, elm ) return MakeImmutable( mat ); end); +InstallMethod( PreImagesRepresentative,"IsProjectiveActionHomomorphism", + FamRangeEqFamElm, [ IsProjectiveActionHomomorphism, IsPerm ], 0, +function( hom, elm ) + if not ( elm in Range( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end); + ############################################################################# ## #A LinearActionBasis() diff --git a/lib/relation.gi b/lib/relation.gi index 115e5409ae..e349d50d5e 100644 --- a/lib/relation.gi +++ b/lib/relation.gi @@ -984,6 +984,7 @@ InstallMethod(ImagesElm, ############################################################################# ## #M PreImagesElmNC( , ) +#M PreImagesElm( , ) ## ## For binary relations over [1..n] represented as a list of images ## @@ -995,6 +996,16 @@ InstallMethod(PreImagesElmNC, i->n in Successors(rel)[i]); end); +InstallMethod(PreImagesElm, + "for binary rels over [1..n] with images list", + true, [IsBinaryRelation and IsBinaryRelationOnPointsRep, IsPosInt], 0, + function( rel, n ) + if not ( n in Range(rel) ) then + return []; + fi; + return PreImagesElm( rel, n ); + end ); + ############################################################################# ## #A Successors( ) @@ -1782,6 +1793,7 @@ InstallMethod( ImagesRepresentative, "equivalence relations", ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . for equivalence relations +#M PreImagesRepresentative( , ) . . . . for equivalence relations ## InstallMethod( PreImagesRepresentativeNC, "equivalence relations", FamRangeEqFamElm, [IsEquivalenceRelation, IsObject], 0, @@ -1789,6 +1801,15 @@ InstallMethod( PreImagesRepresentativeNC, "equivalence relations", return elm; end); +InstallMethod( PreImagesRepresentative, "equivalence relations", + FamRangeEqFamElm, [IsEquivalenceRelation, IsObject], 0, + function( map, elm ) + if not ( elm in Range(map) ) then + return fail; + fi; + return elm; + end); + ############################################################################# ## #M ImagesElm( , ) for equivalence relations with partition @@ -1814,6 +1835,7 @@ InstallMethod( ImagesElm, ############################################################################# ## #M PreImagesElmNC( , ) . for equivalence relations with partition +#M PreImagesElm( , ) . . for equivalence relations with partition ## InstallMethod( PreImagesElmNC, "equivalence relations with partition and element", @@ -1826,6 +1848,18 @@ InstallMethod( PreImagesElmNC, return ImagesElm(rel, elm); end); +InstallMethod( PreImagesElm, + "equivalence relations with partition and element", + FamRangeEqFamElm, + [IsEquivalenceRelation and HasEquivalenceRelationPartition, + IsObject],0, + function( rel, elm ) + if not ( elm in Range( rel ) ) then ##?? is there a Range(rel)? + return []; + fi; + return PreImagesElmNC( rel, elm ); + end); + ############################################################################# ## #M PrintObj( ) for equivalence relation diff --git a/lib/ringhom.gi b/lib/ringhom.gi index 2dc8ab4bb7..6377e0ceec 100644 --- a/lib/ringhom.gi +++ b/lib/ringhom.gi @@ -445,6 +445,7 @@ end ); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . for ring g.m.b.i. +#M PreImagesRepresentative( , ) . . . . . . . for ring g.m.b.i. ## InstallMethod( PreImagesRepresentativeNC, "for ring g.m.b.i., and element", @@ -455,6 +456,18 @@ function( map, elm ) return ImagesRepresentative(InverseGeneralMapping(map),elm); end ); +InstallMethod( PreImagesRepresentative, + "for ring g.m.b.i., and element", + FamRangeEqFamElm, + [ IsRingGeneralMapping and IsRingGeneralMappingByImagesDefaultRep, + IsObject ], +function( map, elm ) + if not ( elm in Range( map ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); +end ); + BindGlobal("IsomorphismSCRing",function(R) local e, z, one, o, sel, g, go, elms, dec, p, cands, m, a, b, nr, hom, i, j; if Size(R)>100000 then diff --git a/lib/vspchom.gi b/lib/vspchom.gi index daf0e145bf..7fe397f6bd 100644 --- a/lib/vspchom.gi +++ b/lib/vspchom.gi @@ -485,6 +485,7 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## +#M PreImagesRepresentative( , ) . . . . for left module g.m.b.i. #M PreImagesRepresentativeNC( , ) . . . for left module g.m.b.i. ## InstallMethod( PreImagesRepresentativeNC, @@ -503,6 +504,17 @@ InstallMethod( PreImagesRepresentativeNC, return LinearCombination( map!.preimagesbasisimage, elm ); end ); +InstallMethod( PreImagesRepresentative, + "for left module g.m.b.i., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsObject ], + function( map, elm ) + if not ( elm in Image( map ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); ############################################################################# ## @@ -1239,6 +1251,18 @@ InstallMethod( PreImagesRepresentativeNC, return LinearCombination( map!.preimagesbasisimage, elm ); end ); +InstallMethod( PreImagesRepresentative, + "for left module m.b.m., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, + IsObject ], + function( map, elm ) + if not ( elm in Image( map ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); + ############################################################################# ## diff --git a/tst/testbugfix/2012-11-25-t00264.tst b/tst/testbugfix/2012-11-25-t00264.tst index 29e0fb14ee..754b367a0d 100644 --- a/tst/testbugfix/2012-11-25-t00264.tst +++ b/tst/testbugfix/2012-11-25-t00264.tst @@ -5,5 +5,7 @@ gap> f := FreeGroup(2); gap> iso:=GroupHomomorphismByImagesNC(f,f,[f.1*f.2,f.1*f.2^2],[f.2^2*f.1,f.2*f.1]); [ f1*f2, f1*f2^2 ] -> [ f2^2*f1, f2*f1 ] gap> SetIsSurjective(iso,true); -gap> Image(iso,PreImagesRepresentative(iso,f.1)); +gap> Image(iso,PreImagesRepresentativeNC(iso,f.1)); f1 +## (20/05/26): gap> Image(iso,PreImagesRepresentative(iso,f.1)); +## cannot be made to work because the code for the NC version is in a package From 5b98560c50db5dbe760147f5a7eb4bcee53def23 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 20 May 2026 19:44:30 +0100 Subject: [PATCH 003/114] adjust documentation in mapping.gd --- lib/mapping.gd | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/lib/mapping.gd b/lib/mapping.gd index 70c0be49a0..497fe25b85 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -751,7 +751,7 @@ DeclareAttribute( "ImagesSource", IsGeneralMapping ); ## ## is the set of preimages of the range of the general mapping map. ##

-## delegates to , +## delegates to , ## it is introduced only to store the preimage of map as attribute ## value. ## @@ -977,16 +977,17 @@ DeclareGlobalFunction( "Images" ); ## ## ## If elm is an element of the range of the general mapping -## map then returns the set of all +## map then returns the set of all ## preimages of elm under map. ##

-## Anything may happen if elm is not an element of the range of -## map. -##

-## In order to improve this state of affairs, -## PreImagesElm has been renamed PreImagesElmNC +## From &GAP; version 4.16.0 +## PreImagesElm was renamed PreImagesElmNC ## throughout the library, and PreImagesElm now checks that ## elm is an element of the range before calling PreImagesElmNC. +##

+## When using PreImagesElmNC anything may happen if elm +## is not an element of the range of map. +##

## ## ## <#/GAPDoc> @@ -1036,13 +1037,14 @@ DeclareOperation( "PreImageElm", ## fail, the latter if and only if elm ## has no preimages under map. ##

-## Anything may happen if elm is not an element of the range of -## map. -##

-## In order to improve this state of affairs, PreImagesRepresentative -## has been renamed PreImagesRepresentativeNC throughout the library, +## From &GAP; version 4.16.0 PreImagesRepresentative +## was renamed PreImagesRepresentativeNC throughout the library, ## and PreImagesRepresentative now checks that elm is an ## element of the range before calling PreImagesRepresentativeNC. +##

+## When using PreImagesRepresentativeNC anything may happen if +## elm is not an element of the range of map. +##

## ## ## <#/GAPDoc> @@ -1066,13 +1068,14 @@ DeclareOperation( "PreImagesRepresentativeNC", [ IsGeneralMapping, IsObject ] ); ## then returns the set of all preimages of ## elms under map. ##

-## Anything may happen if elms is not a subset of the range of -## map. -##

-## In order to improve this state of affairs, PreImagesSet +## From &GAP; version 4.16.0 PreImagesSet ## has been renamed PreImagesSetNC throughout the library, -## and PreImagesSet now checks that elm is an -## element of the range before calling PreImagesSetNC. +## and PreImagesSet now checks that elms is a +## subset of the range before calling PreImagesSetNC. +##

+## When using PreImagesSetNC anything may happen if elms +## is not a subset of the range of map. +##

## ## ## <#/GAPDoc> @@ -1182,15 +1185,18 @@ DeclareGlobalFunction( "PreImage" ); ## entries do in general not correspond.) ##

## -## delegates to when -## called with one argument, +## delegates to when called with one argument, ## and to resp. when ## called with two arguments. ##

-## In order to improve this state of affairs, PreImages +## From &GAP; version 4.16.0 PreImages ## has been renamed PreImagesNC throughout the library, ## and PreImages now checks that elm or coll ## belong to the range before calling PreImagesNC. +##

+## When using PreImagesNC anything may happen if elm +## or coll do not belong to the range of map. +##

## ## ## <#/GAPDoc> From 9fd69482998f54a7089217683471621b0db2fc4d Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 21 May 2026 10:12:07 +0100 Subject: [PATCH 004/114] replace items deleted in error in alghom.gi --- lib/alghom.gi | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/lib/alghom.gi b/lib/alghom.gi index 51147d67cd..15af8ea48d 100644 --- a/lib/alghom.gi +++ b/lib/alghom.gi @@ -916,6 +916,7 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## #M PreImagesRepresentativeNC( , ) +#M PreImagesRepresentative( , ) ## BindGlobal( "PreImagesRepresentativeOperationAlgebraHomomorphism", function( ophom, mat ) if not IsBound( ophom!.basisImage ) then @@ -928,6 +929,22 @@ BindGlobal( "PreImagesRepresentativeOperationAlgebraHomomorphism", function( oph return mat; end ); +InstallMethod( PreImagesRepresentativeNC, + "for an operation algebra homomorphism, and an element", + FamRangeEqFamElm, + [ IsOperationAlgebraHomomorphismDefaultRep, IsMatrix ], + PreImagesRepresentativeOperationAlgebraHomomorphism ); + +InstallMethod( PreImagesRepresentative, + "for an operation algebra homomorphism, and an element", + FamRangeEqFamElm, + [ IsOperationAlgebraHomomorphismDefaultRep, IsMatrix ], + function( ophom, mat ) + if not ( mat in Range( ophom ) ) then + return fail; + fi; + return PreImagesRepresentativeOperationAlgebraHomomorphism( ophom, mat ); +end ); ############################################################################# ## @@ -1081,6 +1098,28 @@ InstallMethod( ImagesRepresentative, end ); +############################################################################# +## +#M PreImagesRepresentativeNC( , ) +#M PreImagesRepresentative( , ) +## +InstallMethod( PreImagesRepresentativeNC, + "for an alg. hom. from f. p. algebra, and an element", + FamRangeEqFamElm, + [ IsAlgebraHomomorphismFromFpRep, IsMatrix ], + PreImagesRepresentativeOperationAlgebraHomomorphism ); + +InstallMethod( PreImagesRepresentativeNC, + "for an alg. hom. from f. p. algebra, and an element", + FamRangeEqFamElm, + [ IsAlgebraHomomorphismFromFpRep, IsMatrix ], + function( ophom, mat ); + if not ( mat in Range( ophom ) ) then + return fail; + fi; + return PreImagesRepresentativeOperationAlgebraHomomorphism( ophom, mat ); + end ); + ############################################################################# ## #M OperationAlgebraHomomorphism( , , ) From 8481a3940d74be25ee6a1ebe1144bd986bb608db Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 21 May 2026 10:17:20 +0100 Subject: [PATCH 005/114] applied fix from stertooy --- lib/ghomfp.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ghomfp.gi b/lib/ghomfp.gi index be891d7ee9..fc045d8289 100644 --- a/lib/ghomfp.gi +++ b/lib/ghomfp.gi @@ -629,7 +629,7 @@ InstallMethod( PreImagesSet, "map from (sub)group of fp group", CollFamRangeEqFamElms, [ IsFromFpGroupHomomorphism,IsGroup ],0, function(hom,u) - if not (u in Range(hom)) then + if not IsSubset( Range(hom), u ) then return []; fi; return PreImagesSetNC(hom,u); From a8e5012e65dbd52f1fb334e5ddfa496839ca404d Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 21 May 2026 17:46:20 +0100 Subject: [PATCH 006/114] minor correction --- lib/alghom.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/alghom.gi b/lib/alghom.gi index 15af8ea48d..b28b163047 100644 --- a/lib/alghom.gi +++ b/lib/alghom.gi @@ -1109,7 +1109,7 @@ InstallMethod( PreImagesRepresentativeNC, [ IsAlgebraHomomorphismFromFpRep, IsMatrix ], PreImagesRepresentativeOperationAlgebraHomomorphism ); -InstallMethod( PreImagesRepresentativeNC, +InstallMethod( PreImagesRepresentative, "for an alg. hom. from f. p. algebra, and an element", FamRangeEqFamElm, [ IsAlgebraHomomorphismFromFpRep, IsMatrix ], From 168d9176686da36b09a663b0942f2fee5d295ef4 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 21 May 2026 18:36:32 +0100 Subject: [PATCH 007/114] another adjustment to bugfix test --- tst/testbugfix/2012-11-25-t00264.tst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tst/testbugfix/2012-11-25-t00264.tst b/tst/testbugfix/2012-11-25-t00264.tst index 754b367a0d..3d570f79c5 100644 --- a/tst/testbugfix/2012-11-25-t00264.tst +++ b/tst/testbugfix/2012-11-25-t00264.tst @@ -1,5 +1,7 @@ # 2012/11/25 (AK) # Fix of a bug that was reproducible in GAP 4.5.6 with FGA 1.1.1 +# (20/05/26): gap> Image(iso,PreImagesRepresentative(iso,f.1)); +# cannot be made to work because the code for the NC version is in a package gap> f := FreeGroup(2); gap> iso:=GroupHomomorphismByImagesNC(f,f,[f.1*f.2,f.1*f.2^2],[f.2^2*f.1,f.2*f.1]); @@ -7,5 +9,3 @@ gap> iso:=GroupHomomorphismByImagesNC(f,f,[f.1*f.2,f.1*f.2^2],[f.2^2*f.1,f.2*f.1 gap> SetIsSurjective(iso,true); gap> Image(iso,PreImagesRepresentativeNC(iso,f.1)); f1 -## (20/05/26): gap> Image(iso,PreImagesRepresentative(iso,f.1)); -## cannot be made to work because the code for the NC version is in a package From e61b7cb1de91e747a9c1d1fcd9071d55ef31607f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 19 May 2026 19:55:29 +0200 Subject: [PATCH 008/114] PackageVariablesInfo: better support variadic functions (#6404) Teach args helper about multi-arg variadic functions. --- lib/package.gi | 9 +++++---- tst/mockpkg/gap/mockpkg.gi | 4 ++++ tst/testinstall/package.tst | 3 ++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/package.gi b/lib/package.gi index 1930c9d6fd..a4b404027e 100644 --- a/lib/package.gi +++ b/lib/package.gi @@ -3348,12 +3348,13 @@ InstallGlobalFunction( PackageVariablesInfo, function( pkgname, version ) fi; num:= NumberArgumentsFunction( func ); nam:= NamesLocalVariablesFunction( func ); - if num = -1 then - str:= "arg"; - elif nam = fail then + if nam = fail then str:= "..."; else - str:= JoinStringsWithSeparator( nam{ [ 1 .. num ] }, ", " ); + str:= JoinStringsWithSeparator( nam{ [ 1 .. AbsInt(num) ] }, ", " ); + if num < 0 then + Append( str, "..." ); + fi; fi; return Concatenation( "( ", str, " )" ); end; diff --git a/tst/mockpkg/gap/mockpkg.gi b/tst/mockpkg/gap/mockpkg.gi index 3bcefc9c79..9ef3c4719a 100644 --- a/tst/mockpkg/gap/mockpkg.gi +++ b/tst/mockpkg/gap/mockpkg.gi @@ -13,3 +13,7 @@ InstallMethod( mockpkg_Operation, [ IsGroup, IsPosInt ], { G, n } -> n ); InstallMethod( mockpkg_Attribute, [ IsSolvableGroup ], G -> G ); InstallMethod( mockpkg_Property, [ IsNilpotentGroup ], IsAbelian ); + +BindGlobal( "mockpkg_Vararg", function(first, rest...) + return Concatenation([first], rest); +end ); diff --git a/tst/testinstall/package.tst b/tst/testinstall/package.tst index 2b1a5d6e84..48df3fbf39 100644 --- a/tst/testinstall/package.tst +++ b/tst/testinstall/package.tst @@ -450,9 +450,10 @@ new global functions: new global variables: mockpkg_ExtensionData* + mockpkg_Vararg( first, rest... )* new operations: - mockpkg_Operation( arg )* + mockpkg_Operation( ... )* new attributes: mockpkg_Attribute( ... )* From f496cdae391b87efd32a03148d8488bd89bf6673 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 21 May 2026 16:45:42 +0200 Subject: [PATCH 009/114] kernel: strengthen vecgf2 and vec8bit validation, reject empty vectors were not supported (#6401) Add runtime argument checks to the user-facing GF2 and 8-bit kernel entry points instead of relying on debug-only assertions or unchecked representation assumptions. Use shared Require helpers for compressed vectors and matrices, and tighten plain-list validation where these entry points expect list-backed inputs. Harden the exported vec8bit kernel entry points that assumed a first row existed, and fix SHIFT_VEC8BIT_RIGHT for empty compressed vectors. AI assistance from OpenAI Codex helped prepare these kernel validation changes. Co-authored-by: Codex --- src/vec8bit.c | 187 ++++- src/vecgf2.c | 158 +++- src/vecgf2.h | 8 + tst/testinstall/kernel/vec8bit.tst | 1187 ++++++++++++++++++++++++++++ tst/testinstall/kernel/vecgf2.tst | 973 ++++++++++++++++++++++- 5 files changed, 2459 insertions(+), 54 deletions(-) diff --git a/src/vec8bit.c b/src/vec8bit.c index 9137672f8c..3b50507c67 100644 --- a/src/vec8bit.c +++ b/src/vec8bit.c @@ -60,6 +60,10 @@ RequireArgumentCondition(funcname, op, IS_MAT8BIT_REP(op), \ "must belong to Is8BitMatrixRep") +#define RequireFFE(funcname, op) \ + RequireArgumentCondition(funcname, op, IS_FFE(op), \ + "must be a finite field element") + /**************************************************************************** ** *F IS_VEC8BIT_REP( ) . . . check that is in 8bit GFQ vector rep @@ -815,6 +819,7 @@ static UInt LcmDegree(UInt d, UInt d1) */ static Obj FuncCONV_VEC8BIT(Obj self, Obj list, Obj q) { + RequireSmallList(SELF_NAME, list); UInt iq = GetPositiveSmallInt(SELF_NAME, q); ConvVec8Bit(list, iq); return 0; @@ -937,6 +942,7 @@ static Obj NewVec8Bit(Obj list, UInt q) */ static Obj FuncCOPY_VEC8BIT(Obj self, Obj list, Obj q) { + RequireSmallList(SELF_NAME, list); UInt iq = GetPositiveSmallInt(SELF_NAME, q); return NewVec8Bit(list, iq); } @@ -1019,9 +1025,7 @@ void PlainVec8Bit(Obj list) */ static Obj FuncPLAIN_VEC8BIT(Obj self, Obj list) { - if (!IS_VEC8BIT_REP(list)) { - RequireArgument(SELF_NAME, list, "must be an 8bit vector"); - } + RequireVec8BitRep(SELF_NAME, list); if (DoFilter(IsLockedRepresentationVector, list) == True) { ErrorMayQuit("Cannot convert a locked vector compressed over " "GF(%d) to a plain list", @@ -1214,8 +1218,8 @@ static Obj ConvertToVectorRep; // BH: changed to static static Obj FuncSUM_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) { - GAP_ASSERT(IS_VEC8BIT_REP(vl)); - GAP_ASSERT(IS_VEC8BIT_REP(vr)); + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); Obj sum; if (FIELD_VEC8BIT(vl) != FIELD_VEC8BIT(vr)) { @@ -1395,6 +1399,9 @@ static Obj FuncPROD_VEC8BIT_FFE(Obj self, Obj vec, Obj ffe) Obj info; UInt d; + RequireVec8BitRep(SELF_NAME, vec); + RequireFFE(SELF_NAME, ffe); + if (VAL_FFE(ffe) == 1) { // ffe is the one return CopyVec8Bit(vec, IS_MUTABLE_OBJ(vec)); } @@ -1427,6 +1434,7 @@ static Obj FuncPROD_VEC8BIT_FFE(Obj self, Obj vec, Obj ffe) static Obj FuncZERO_VEC8BIT(Obj self, Obj vec) { + RequireVec8BitRep(SELF_NAME, vec); return ZeroVec8Bit(FIELD_VEC8BIT(vec), LEN_VEC8BIT(vec), 1); } @@ -1456,6 +1464,8 @@ static Obj FuncZERO_VEC8BIT_2(Obj self, Obj q, Obj len) static Obj FuncPROD_FFE_VEC8BIT(Obj self, Obj ffe, Obj vec) { + RequireFFE(SELF_NAME, ffe); + RequireVec8BitRep(SELF_NAME, vec); return FuncPROD_VEC8BIT_FFE(self, vec, ffe); } @@ -1492,16 +1502,19 @@ static Obj AInvVec8Bit(Obj vec, UInt mut) static Obj FuncAINV_VEC8BIT_MUTABLE(Obj self, Obj vec) { + RequireVec8BitRep(SELF_NAME, vec); return AInvVec8Bit(vec, 1); } static Obj FuncAINV_VEC8BIT_SAME_MUTABILITY(Obj self, Obj vec) { + RequireVec8BitRep(SELF_NAME, vec); return AInvVec8Bit(vec, IS_MUTABLE_OBJ(vec)); } static Obj FuncAINV_VEC8BIT_IMMUTABLE(Obj self, Obj vec) { + RequireVec8BitRep(SELF_NAME, vec); return AInvVec8Bit(vec, 0); } @@ -1608,6 +1621,8 @@ static void AddVec8BitVec8BitMultInner( static Obj FuncMULT_VECTOR_VEC8BITS(Obj self, Obj vec, Obj mul) { + RequireVec8BitRep(SELF_NAME, vec); + RequireFFE(SELF_NAME, mul); UInt q; q = FIELD_VEC8BIT(vec); @@ -1646,6 +1661,11 @@ static Obj AddRowVector; static Obj FuncADD_ROWVECTOR_VEC8BITS_5( Obj self, Obj vl, Obj vr, Obj mul, Obj from, Obj to) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); + RequireFFE(SELF_NAME, mul); + RequirePositiveSmallInt(SELF_NAME, from); + RequirePositiveSmallInt(SELF_NAME, to); UInt q; UInt len; len = LEN_VEC8BIT(vl); @@ -1720,6 +1740,9 @@ static Obj FuncADD_ROWVECTOR_VEC8BITS_5( static Obj FuncADD_ROWVECTOR_VEC8BITS_3(Obj self, Obj vl, Obj vr, Obj mul) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); + RequireFFE(SELF_NAME, mul); UInt q; if (LEN_VEC8BIT(vl) != LEN_VEC8BIT(vr)) { ErrorMayQuit( @@ -1778,6 +1801,8 @@ static Obj FuncADD_ROWVECTOR_VEC8BITS_3(Obj self, Obj vl, Obj vr, Obj mul) static Obj FuncADD_ROWVECTOR_VEC8BITS_2(Obj self, Obj vl, Obj vr) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); UInt q; if (LEN_VEC8BIT(vl) != LEN_VEC8BIT(vr)) { ErrorMayQuit( @@ -1913,6 +1938,8 @@ static Obj FuncDIFF_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) Obj diff; // UInt p; + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); if (FIELD_VEC8BIT(vl) != FIELD_VEC8BIT(vr)) { UInt ql = FIELD_VEC8BIT(vl), qr = FIELD_VEC8BIT(vr); @@ -2086,6 +2113,8 @@ static Obj ScalarProductVec8Bits(Obj vl, Obj vr) static Obj FuncPROD_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); if (FIELD_VEC8BIT(vl) != FIELD_VEC8BIT(vr)) return ProdListList(vl, vr); @@ -2146,6 +2175,8 @@ static UInt DistanceVec8Bits(Obj vl, Obj vr) static Obj FuncDISTANCE_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); if (FIELD_VEC8BIT(vl) != FIELD_VEC8BIT(vr) || LEN_VEC8BIT(vl) != LEN_VEC8BIT(vr)) return TRY_NEXT_METHOD; @@ -2215,6 +2246,10 @@ static Obj FuncDISTANCE_DISTRIB_VEC8BITS( UInt len; UInt q; + RequirePlainList(SELF_NAME, veclis); + RequireVec8BitRep(SELF_NAME, vec); + RequirePlainList(SELF_NAME, d); + len = LEN_VEC8BIT(vec); q = FIELD_VEC8BIT(vec); @@ -2331,6 +2366,8 @@ static Obj FuncA_CLOSEST_VEC8BIT( UInt len; UInt q; + RequirePlainList(SELF_NAME, veclis); + RequireVec8BitRep(SELF_NAME, vec); RequireNonnegativeSmallInt(SELF_NAME, cnt); RequireNonnegativeSmallInt(SELF_NAME, stop); @@ -2371,6 +2408,8 @@ static Obj FuncA_CLOSEST_VEC8BIT_COORDS( Obj res; + RequirePlainList(SELF_NAME, veclis); + RequireVec8BitRep(SELF_NAME, vec); RequireNonnegativeSmallInt(SELF_NAME, cnt); RequireNonnegativeSmallInt(SELF_NAME, stop); @@ -2413,6 +2452,7 @@ static Obj FuncA_CLOSEST_VEC8BIT_COORDS( static Obj FuncNUMBER_VEC8BIT(Obj self, Obj vec) { + RequireVec8BitRep(SELF_NAME, vec); Obj info; UInt elts; UInt len; @@ -2608,6 +2648,7 @@ static Obj FuncCOSET_LEADERS_INNER_8BITS( RequireSmallInt(SELF_NAME, weight); RequireSmallInt(SELF_NAME, tofind); RequirePlainList(SELF_NAME, leaders); + RequirePlainList(SELF_NAME, felts); lenv = LEN_PLIST(veclis); q = LEN_PLIST(felts); @@ -2628,6 +2669,8 @@ static Obj FuncCOSET_LEADERS_INNER_8BITS( static Obj FuncEQ_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); if (FIELD_VEC8BIT(vl) != FIELD_VEC8BIT(vr)) return EqListList(vl, vr) ? True : False; @@ -2645,6 +2688,8 @@ static Obj FuncEQ_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) static Obj FuncLT_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); if (FIELD_VEC8BIT(vl) != FIELD_VEC8BIT(vr)) return LtListList(vl, vr) ? True : False; @@ -2665,6 +2710,7 @@ static Obj FuncLT_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) static Obj FuncSHALLOWCOPY_VEC8BIT(Obj self, Obj list) { + RequireVec8BitRep(SELF_NAME, list); return CopyVec8Bit(list, 1); } @@ -2675,6 +2721,7 @@ static Obj FuncSHALLOWCOPY_VEC8BIT(Obj self, Obj list) */ static Obj FuncLEN_VEC8BIT(Obj self, Obj list) { + RequireVec8BitRep(SELF_NAME, list); return INTOBJ_INT(LEN_VEC8BIT(list)); } @@ -2684,6 +2731,7 @@ static Obj FuncLEN_VEC8BIT(Obj self, Obj list) */ static Obj FuncQ_VEC8BIT(Obj self, Obj list) { + RequireVec8BitRep(SELF_NAME, list); return INTOBJ_INT(FIELD_VEC8BIT(list)); } @@ -2704,6 +2752,7 @@ static Obj FuncELM0_VEC8BIT(Obj self, Obj list, Obj pos) Obj info; UInt elts; + RequireVec8BitRep(SELF_NAME, list); p = GetPositiveSmallInt(SELF_NAME, pos); if (LEN_VEC8BIT(list) < p) { return Fail; @@ -2733,6 +2782,7 @@ static Obj FuncELM_VEC8BIT(Obj self, Obj list, Obj pos) Obj info; UInt elts; + RequireVec8BitRep(SELF_NAME, list); p = GetPositiveSmallInt(SELF_NAME, pos); if (LEN_VEC8BIT(list) < p) { ErrorMayQuit("List Element: [%d] must have an assigned value", @@ -2773,6 +2823,8 @@ static Obj FuncELMS_VEC8BIT(Obj self, Obj list, Obj poss) UInt1 byte; UInt len2; + RequireVec8BitRep(SELF_NAME, list); + RequirePlainList(SELF_NAME, poss); len = LEN_PLIST(poss); info = GetFieldInfo8Bit(FIELD_VEC8BIT(list)); len2 = LEN_VEC8BIT(list); @@ -2840,6 +2892,9 @@ static Obj FuncELMS_VEC8BIT_RANGE(Obj self, Obj list, Obj range) UInt e; UInt1 byte; + RequireVec8BitRep(SELF_NAME, list); + RequireArgumentCondition(SELF_NAME, range, IS_RANGE(range), "must be a range"); + info = GetFieldInfo8Bit(FIELD_VEC8BIT(list)); elts = ELS_BYTE_FIELDINFO_8BIT(info); len = GET_LEN_RANGE(range); @@ -3012,6 +3067,7 @@ void ASS_VEC8BIT(Obj list, Obj pos, Obj elm) static Obj FuncASS_VEC8BIT(Obj self, Obj list, Obj pos, Obj elm) { + RequireVec8BitRep(SELF_NAME, list); ASS_VEC8BIT(list, pos, elm); return 0; } @@ -3032,6 +3088,7 @@ static Obj FuncUNB_VEC8BIT(Obj self, Obj list, Obj pos) Obj info; UInt elts; + RequireVec8BitRep(SELF_NAME, list); // check that is mutable RequireMutable("List Unbind", list, "list"); if (True == DoFilter(IsLockedRepresentationVector, list)) { @@ -3121,12 +3178,15 @@ static UInt PositionNonZeroVec8Bit(Obj list, UInt from) static Obj FuncPOSITION_NONZERO_VEC8BIT(Obj self, Obj list, Obj zero) { + RequireVec8BitRep(SELF_NAME, list); return INTOBJ_INT(PositionNonZeroVec8Bit(list, 0)); } static Obj FuncPOSITION_NONZERO_VEC8BIT3(Obj self, Obj list, Obj zero, Obj from) { + RequireVec8BitRep(SELF_NAME, list); + RequireNonnegativeSmallInt(SELF_NAME, from); return INTOBJ_INT(PositionNonZeroVec8Bit(list, INT_INTOBJ(from))); } @@ -3150,6 +3210,9 @@ static Obj FuncAPPEND_VEC8BIT(Obj self, Obj vecl, Obj vecr) const UInt1 * settab; UInt posl, posr; + RequireVec8BitRep(SELF_NAME, vecl); + RequireVec8BitRep(SELF_NAME, vecr); + if (FIELD_VEC8BIT(vecl) != FIELD_VEC8BIT(vecr)) return TRY_NEXT_METHOD; @@ -3224,6 +3287,9 @@ static Obj FuncPROD_VEC8BIT_MATRIX(Obj self, Obj vec, Obj mat) const Obj * ffefelt; Obj x; + RequireVec8BitRep(SELF_NAME, vec); + RequirePlainList(SELF_NAME, mat); + len = LEN_VEC8BIT(vec); l2 = LEN_PLIST(mat); q = FIELD_VEC8BIT(vec); @@ -3310,6 +3376,14 @@ static inline UInt NR_COLS_MAT8BIT(Obj mat) return LEN_VEC8BIT(ELM_MAT8BIT(mat, 1)); } +static inline void RequireNonemptyMat8BitRows(const Char * funcname, Obj mat) +{ + if (LEN_MAT8BIT(mat) == 0) + ErrorMayQuit("%s: compressed 8bit matrices with empty rows are not " + "supported", + (Int)funcname, 0); +} + /**************************************************************************** ** *F PlainMat8Bit( ) @@ -3337,6 +3411,7 @@ static void PlainMat8Bit(Obj mat) static Obj FuncPLAIN_MAT8BIT(Obj self, Obj mat) { + RequireMat8BitRep(SELF_NAME, mat); PlainMat8Bit(mat); return 0; } @@ -3356,6 +3431,7 @@ static Obj FuncCONV_MAT8BIT(Obj self, Obj list, Obj q) Obj tmp; Obj type; + RequirePlainList(SELF_NAME, list); UInt iq = GetPositiveSmallInt(SELF_NAME, q); PLAIN_LIST(list); len = LEN_PLIST(list); @@ -3464,8 +3540,9 @@ static Obj FuncPROD_VEC8BIT_MAT8BIT(Obj self, Obj vec, Obj mat) { UInt q, q1, q2; - GAP_ASSERT(IS_VEC8BIT_REP(vec)); - GAP_ASSERT(IS_MAT8BIT_REP(mat)); + RequireVec8BitRep(SELF_NAME, vec); + RequireMat8BitRep(SELF_NAME, mat); + RequireNonemptyMat8BitRows(SELF_NAME, mat); // Now field mismatches -- consider promoting the vector q = FIELD_VEC8BIT(vec); @@ -3549,8 +3626,9 @@ static Obj FuncPROD_MAT8BIT_VEC8BIT(Obj self, Obj mat, Obj vec) { UInt q, q1, q2; - GAP_ASSERT(IS_MAT8BIT_REP(mat)); - GAP_ASSERT(IS_VEC8BIT_REP(vec)); + RequireMat8BitRep(SELF_NAME, mat); + RequireVec8BitRep(SELF_NAME, vec); + RequireNonemptyMat8BitRows(SELF_NAME, mat); // Now field mismatches -- consider promoting the vector q = FIELD_VEC8BIT(vec); @@ -3626,8 +3704,10 @@ static Obj ProdMat8BitMat8Bit(Obj matl, Obj matr) static Obj FuncPROD_MAT8BIT_MAT8BIT(Obj self, Obj matl, Obj matr) { - GAP_ASSERT(IS_MAT8BIT_REP(matl)); - GAP_ASSERT(IS_MAT8BIT_REP(matr)); + RequireMat8BitRep(SELF_NAME, matl); + RequireMat8BitRep(SELF_NAME, matr); + RequireNonemptyMat8BitRows(SELF_NAME, matl); + RequireNonemptyMat8BitRows(SELF_NAME, matr); if (FIELD_MAT8BIT(matl) != FIELD_MAT8BIT(matr)) { return TRY_NEXT_METHOD; @@ -3802,7 +3882,8 @@ static Obj InverseMat8Bit(Obj mat, UInt mut) static Obj FuncINV_MAT8BIT_MUTABLE(Obj self, Obj mat) { - GAP_ASSERT(IS_MAT8BIT_REP(mat)); + RequireMat8BitRep(SELF_NAME, mat); + RequireNonemptyMat8BitRows(SELF_NAME, mat); if (LEN_MAT8BIT(mat) != LEN_VEC8BIT(ELM_MAT8BIT(mat, 1))) { ErrorMayQuit("InverseOp: matrix must be square, not %d by %d", @@ -3820,7 +3901,8 @@ static Obj FuncINV_MAT8BIT_MUTABLE(Obj self, Obj mat) static Obj FuncINV_MAT8BIT_SAME_MUTABILITY(Obj self, Obj mat) { - GAP_ASSERT(IS_MAT8BIT_REP(mat)); + RequireMat8BitRep(SELF_NAME, mat); + RequireNonemptyMat8BitRows(SELF_NAME, mat); if (LEN_MAT8BIT(mat) != LEN_VEC8BIT(ELM_MAT8BIT(mat, 1))) { ErrorMayQuit( "InverseSameMutability: matrix must be square, not %d by %d", @@ -3838,7 +3920,8 @@ static Obj FuncINV_MAT8BIT_SAME_MUTABILITY(Obj self, Obj mat) static Obj FuncINV_MAT8BIT_IMMUTABLE(Obj self, Obj mat) { - GAP_ASSERT(IS_MAT8BIT_REP(mat)); + RequireMat8BitRep(SELF_NAME, mat); + RequireNonemptyMat8BitRows(SELF_NAME, mat); if (LEN_MAT8BIT(mat) != LEN_VEC8BIT(ELM_MAT8BIT(mat, 1))) { ErrorMayQuit("Inverse: matrix must be square, not %d by %d", LEN_MAT8BIT(mat), LEN_VEC8BIT(ELM_MAT8BIT(mat, 1))); @@ -3864,7 +3947,8 @@ static Obj FuncASS_MAT8BIT(Obj self, Obj mat, Obj pos, Obj obj) UInt p; Obj type; - GAP_ASSERT(IS_MAT8BIT_REP(mat)); + RequireMat8BitRep(SELF_NAME, mat); + RequireNonemptyMat8BitRows(SELF_NAME, mat); p = GetPositiveSmallInt(SELF_NAME, pos); len = LEN_MAT8BIT(mat); @@ -3957,7 +4041,7 @@ static Obj FuncASS_MAT8BIT(Obj self, Obj mat, Obj pos, Obj obj) */ static Obj FuncELM_MAT8BIT(Obj self, Obj mat, Obj pos) { - GAP_ASSERT(IS_MAT8BIT_REP(mat)); + RequireMat8BitRep(SELF_NAME, mat); UInt r = GetPositiveSmallInt(SELF_NAME, pos); if (LEN_MAT8BIT(mat) < r) { ErrorMayQuit("row index %d exceeds %d, the number of rows", r, @@ -4111,8 +4195,10 @@ static Obj SumMat8BitMat8Bit(Obj ml, Obj mr) static Obj FuncSUM_MAT8BIT_MAT8BIT(Obj self, Obj ml, Obj mr) { - GAP_ASSERT(IS_MAT8BIT_REP(ml)); - GAP_ASSERT(IS_MAT8BIT_REP(mr)); + RequireMat8BitRep(SELF_NAME, ml); + RequireMat8BitRep(SELF_NAME, mr); + RequireNonemptyMat8BitRows(SELF_NAME, ml); + RequireNonemptyMat8BitRows(SELF_NAME, mr); if (FIELD_MAT8BIT(ml) != FIELD_MAT8BIT(mr)) { return TRY_NEXT_METHOD; @@ -4204,8 +4290,10 @@ static Obj DiffMat8BitMat8Bit(Obj ml, Obj mr) static Obj FuncDIFF_MAT8BIT_MAT8BIT(Obj self, Obj ml, Obj mr) { - GAP_ASSERT(IS_MAT8BIT_REP(ml)); - GAP_ASSERT(IS_MAT8BIT_REP(mr)); + RequireMat8BitRep(SELF_NAME, ml); + RequireMat8BitRep(SELF_NAME, mr); + RequireNonemptyMat8BitRows(SELF_NAME, ml); + RequireNonemptyMat8BitRows(SELF_NAME, mr); if (FIELD_MAT8BIT(ml) != FIELD_MAT8BIT(mr)) return TRY_NEXT_METHOD; @@ -4407,6 +4495,8 @@ static void ShiftRightVec8Bit(Obj vec, UInt amount) // pads with zeros // make room len = LEN_VEC8BIT(vec); ResizeVec8Bit(vec, len + amount, 0); + if (len == 0) + return; q = FIELD_VEC8BIT(vec); info = GetFieldInfo8Bit(q); @@ -4461,6 +4551,10 @@ static void ShiftRightVec8Bit(Obj vec, UInt amount) // pads with zeros static Obj FuncADD_COEFFS_VEC8BIT_3(Obj self, Obj vec1, Obj vec2, Obj mult) { + RequireVec8BitRep(SELF_NAME, vec1); + RequireVec8BitRep(SELF_NAME, vec2); + RequireFFE(SELF_NAME, mult); + UInt q; UInt len; len = LEN_VEC8BIT(vec2); @@ -4525,6 +4619,9 @@ static Obj FuncADD_COEFFS_VEC8BIT_3(Obj self, Obj vec1, Obj vec2, Obj mult) static Obj FuncADD_COEFFS_VEC8BIT_2(Obj self, Obj vec1, Obj vec2) { + RequireVec8BitRep(SELF_NAME, vec1); + RequireVec8BitRep(SELF_NAME, vec2); + UInt q; UInt len; len = LEN_VEC8BIT(vec2); @@ -4578,8 +4675,8 @@ static Obj FuncADD_COEFFS_VEC8BIT_2(Obj self, Obj vec1, Obj vec2) static Obj FuncSHIFT_VEC8BIT_LEFT(Obj self, Obj vec, Obj amount) { - if (!IS_MUTABLE_OBJ(vec)) - RequireArgument(SELF_NAME, vec, "must be mutable"); + RequireVec8BitRep(SELF_NAME, vec); + RequireMutable(SELF_NAME, vec, "vector"); RequireNonnegativeSmallInt(SELF_NAME, amount); ShiftLeftVec8Bit(vec, INT_INTOBJ(amount)); return (Obj)0; @@ -4593,9 +4690,10 @@ static Obj FuncSHIFT_VEC8BIT_LEFT(Obj self, Obj vec, Obj amount) static Obj FuncSHIFT_VEC8BIT_RIGHT(Obj self, Obj vec, Obj amount, Obj zero) { - if (!IS_MUTABLE_OBJ(vec)) - RequireArgument(SELF_NAME, vec, "must be mutable"); + RequireVec8BitRep(SELF_NAME, vec); + RequireMutable(SELF_NAME, vec, "vector"); RequireNonnegativeSmallInt(SELF_NAME, amount); + RequireFFE(SELF_NAME, zero); ShiftRightVec8Bit(vec, INT_INTOBJ(amount)); return (Obj)0; } @@ -4608,6 +4706,7 @@ static Obj FuncSHIFT_VEC8BIT_RIGHT(Obj self, Obj vec, Obj amount, Obj zero) static Obj FuncRESIZE_VEC8BIT(Obj self, Obj vec, Obj newsize) { + RequireVec8BitRep(SELF_NAME, vec); RequireMutable(SELF_NAME, vec, "vector"); RequireNonnegativeSmallInt(SELF_NAME, newsize); ResizeVec8Bit(vec, INT_INTOBJ(newsize), 0); @@ -4622,6 +4721,7 @@ static Obj FuncRESIZE_VEC8BIT(Obj self, Obj vec, Obj newsize) static Obj FuncRIGHTMOST_NONZERO_VEC8BIT(Obj self, Obj vec) { + RequireVec8BitRep(SELF_NAME, vec); return INTOBJ_INT(RightMostNonZeroVec8Bit(vec)); } @@ -4807,6 +4907,12 @@ static Obj FuncPROD_COEFFS_VEC8BIT(Obj self, Obj vl, Obj ll, Obj vr, Obj lr) Obj res; UInt lenp; UInt last; + + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); + RequireNonnegativeSmallInt(SELF_NAME, ll); + RequireNonnegativeSmallInt(SELF_NAME, lr); + q = FIELD_VEC8BIT(vl); if (q != FIELD_VEC8BIT(vr)) { Obj info1; @@ -4837,8 +4943,6 @@ static Obj FuncPROD_COEFFS_VEC8BIT(Obj self, Obj vl, Obj ll, Obj vr, Obj lr) q = q0; } - RequireNonnegativeSmallInt(SELF_NAME, ll); - RequireNonnegativeSmallInt(SELF_NAME, lr); ll1 = INT_INTOBJ(ll); lr1 = INT_INTOBJ(lr); if (0 > ll1 || ll1 > LEN_VEC8BIT(vl)) @@ -4855,7 +4959,8 @@ static Obj FuncPROD_COEFFS_VEC8BIT(Obj self, Obj vl, Obj ll, Obj vr, Obj lr) else lenp = ll1 + lr1 - 1; res = ZeroVec8Bit(q, lenp, 1); - ProdCoeffsVec8Bit(res, vl, ll1, vr, lr1); + if (lenp > 0) + ProdCoeffsVec8Bit(res, vl, ll1, vr, lr1); last = RightMostNonZeroVec8Bit(res); if (last != lenp) ResizeVec8Bit(res, last, 1); @@ -5060,10 +5165,11 @@ static Obj FuncREDUCE_COEFFS_VEC8BIT(Obj self, Obj vl, Obj ll, Obj vrshifted) UInt last; RequireVec8BitRep(SELF_NAME, vl); + RequireNonnegativeSmallInt(SELF_NAME, ll); + RequirePlainList(SELF_NAME, vrshifted); q = FIELD_VEC8BIT(vl); if (q != FIELD_VEC8BIT(ELM_PLIST(vrshifted, 1))) return Fail; - RequireNonnegativeSmallInt(SELF_NAME, ll); if (INT_INTOBJ(ll) > LEN_VEC8BIT(vl)) { ErrorQuit("ReduceCoeffs: given length of left argt (%d) is " "longer than the argt (%d)", @@ -5397,7 +5503,7 @@ static Obj FuncSEMIECHELON_LIST_VEC8BITS(Obj self, Obj mat) Obj row; UInt q; - GAP_ASSERT(IS_PLIST(mat)); + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) @@ -5436,7 +5542,7 @@ static Obj FuncSEMIECHELON_LIST_VEC8BITS_TRANSFORMATIONS(Obj self, Obj mat) UInt q; UInt width; - GAP_ASSERT(IS_PLIST(mat)); + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) @@ -5475,7 +5581,7 @@ static Obj FuncTRIANGULIZE_LIST_VEC8BITS(Obj self, Obj mat) Obj row; UInt q; - GAP_ASSERT(IS_PLIST(mat)); + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) @@ -5514,7 +5620,7 @@ static Obj FuncRANK_LIST_VEC8BITS(Obj self, Obj mat) Obj row; UInt q; - GAP_ASSERT(IS_PLIST(mat)); + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) @@ -5553,7 +5659,7 @@ static Obj FuncDETERMINANT_LIST_VEC8BITS(Obj self, Obj mat) UInt q; Obj det; - GAP_ASSERT(IS_PLIST(mat)); + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) @@ -5613,8 +5719,8 @@ static Int Cmp_MAT8BIT_MAT8BIT(Obj ml, Obj mr) static Obj FuncEQ_MAT8BIT_MAT8BIT(Obj self, Obj ml, Obj mr) { - GAP_ASSERT(IS_MAT8BIT_REP(ml)); - GAP_ASSERT(IS_MAT8BIT_REP(mr)); + RequireMat8BitRep(SELF_NAME, ml); + RequireMat8BitRep(SELF_NAME, mr); if (LEN_MAT8BIT(ml) != LEN_MAT8BIT(mr)) return False; @@ -5632,8 +5738,8 @@ static Obj FuncEQ_MAT8BIT_MAT8BIT(Obj self, Obj ml, Obj mr) static Obj FuncLT_MAT8BIT_MAT8BIT(Obj self, Obj ml, Obj mr) { - GAP_ASSERT(IS_MAT8BIT_REP(ml)); - GAP_ASSERT(IS_MAT8BIT_REP(mr)); + RequireMat8BitRep(SELF_NAME, ml); + RequireMat8BitRep(SELF_NAME, mr); if (LEN_MAT8BIT(ml) == 0) return (LEN_MAT8BIT(mr) != 0) ? True : False; @@ -5665,6 +5771,7 @@ static Obj FuncTRANSPOSED_MAT8BIT(Obj self, Obj mat) Obj type; RequireMat8BitRep(SELF_NAME, mat); + RequireNonemptyMat8BitRows(SELF_NAME, mat); // we will give result same type as mat // we assume here that there is a first row -- a zero row mat8bit is a @@ -5762,8 +5869,10 @@ static Obj FuncKRONECKERPRODUCT_MAT8BIT_MAT8BIT(Obj self, Obj matl, Obj matr) const UInt1 * getelt, *setelt, *scalar, *add; const UInt1 * datar; - GAP_ASSERT(IS_MAT8BIT_REP(matl)); - GAP_ASSERT(IS_MAT8BIT_REP(matr)); + RequireMat8BitRep(SELF_NAME, matl); + RequireMat8BitRep(SELF_NAME, matr); + RequireNonemptyMat8BitRows(SELF_NAME, matl); + RequireNonemptyMat8BitRows(SELF_NAME, matr); nrowl = LEN_MAT8BIT(matl); nrowr = LEN_MAT8BIT(matr); diff --git a/src/vecgf2.c b/src/vecgf2.c index 6c3e64a1c2..b3c7454cb0 100644 --- a/src/vecgf2.c +++ b/src/vecgf2.c @@ -86,6 +86,8 @@ Obj TYPE_LIST_GF2MAT_IMM; */ Obj IsGF2VectorRep; +Obj IsGF2MatrixRep; + /**************************************************************************** ** @@ -100,6 +102,18 @@ static Obj GF2One; */ static Obj GF2Zero; +#define RequireGF2VecRep(funcname, op) \ + RequireArgumentCondition(funcname, op, IS_GF2VEC_REP(op), \ + "must be a GF2 vector") + +#define RequireGF2MatRep(funcname, op) \ + RequireArgumentCondition(funcname, op, IS_GF2MAT_REP(op), \ + "must be a GF2 matrix") + +#define RequireFFE(funcname, op) \ + RequireArgumentCondition(funcname, op, IS_FFE(op), \ + "must be a finite field element") + /**************************************************************************** ** @@ -835,6 +849,12 @@ static Obj FuncPROD_GF2VEC_ANYMAT(Obj self, Obj vec, Obj mat) UInt i; UInt block = 0; + RequireGF2VecRep(SELF_NAME, vec); + RequirePlainList(SELF_NAME, mat); + + if (LEN_PLIST(mat) == 0) + return TRY_NEXT_METHOD; + len = LEN_GF2VEC(vec); if (len > LEN_PLIST(mat)) len = LEN_PLIST(mat); @@ -1389,6 +1409,7 @@ static void ConvGF2Vec(Obj list) */ static Obj FuncCONV_GF2VEC(Obj self, Obj list) { + RequireSmallList(SELF_NAME, list); ConvGF2Vec(list); return 0; } @@ -1467,7 +1488,6 @@ static Obj NewGF2Vec(Obj list) return res; } - /**************************************************************************** ** *F FuncCOPY_GF2VEC( , ) . . . . . convert into a GF2 vector rep @@ -1492,6 +1512,7 @@ static Obj FuncCONV_GF2MAT(Obj self, Obj list) UInt len, i; Obj tmp; UInt mut; + RequireSmallList(SELF_NAME, list); len = LEN_LIST(list); if (len == 0) return (Obj)0; @@ -1664,6 +1685,9 @@ static Int Cmp_GF2VEC_GF2VEC(Obj vl, Obj vr) */ static Obj FuncEQ_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) { + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); + // we can do this case MUCH faster if we just want equality if (LEN_GF2VEC(vl) != LEN_GF2VEC(vr)) return False; @@ -1677,6 +1701,7 @@ static Obj FuncEQ_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) */ static Obj FuncLEN_GF2VEC(Obj self, Obj list) { + RequireGF2VecRep(SELF_NAME, list); return INTOBJ_INT(LEN_GF2VEC(list)); } @@ -1692,6 +1717,7 @@ static Obj FuncLEN_GF2VEC(Obj self, Obj list) */ static Obj FuncELM0_GF2VEC(Obj self, Obj list, Obj pos) { + RequireGF2VecRep(SELF_NAME, list); UInt p = GetSmallInt(SELF_NAME, pos); if (LEN_GF2VEC(list) < p) { return Fail; @@ -1712,6 +1738,7 @@ static Obj FuncELM0_GF2VEC(Obj self, Obj list, Obj pos) */ static Obj FuncELM_GF2VEC(Obj self, Obj list, Obj pos) { + RequireGF2VecRep(SELF_NAME, list); UInt p = GetSmallInt(SELF_NAME, pos); if (LEN_GF2VEC(list) < p) { ErrorMayQuit("List Element: [%d] must have an assigned value", @@ -1743,6 +1770,8 @@ static Obj FuncELMS_GF2VEC(Obj self, Obj list, Obj poss) Int i; // loop variable Obj apos; + RequireGF2VecRep(SELF_NAME, list); + // get the length of lenList = LEN_GF2VEC(list); @@ -1830,6 +1859,8 @@ static Obj FuncELMS_GF2VEC(Obj self, Obj list, Obj poss) static Obj FuncASS_GF2VEC(Obj self, Obj list, Obj pos, Obj elm) { + RequireGF2VecRep(SELF_NAME, list); + // check that is mutable RequireMutable("List Assignment", list, "list"); @@ -1875,6 +1906,7 @@ static Obj FuncASS_GF2VEC(Obj self, Obj list, Obj pos, Obj elm) */ static Obj FuncPLAIN_GF2MAT(Obj self, Obj list) { + RequireGF2MatRep(SELF_NAME, list); PlainGF2Mat(list); return 0; } @@ -1892,6 +1924,8 @@ static Obj FuncPLAIN_GF2MAT(Obj self, Obj list) */ static Obj FuncASS_GF2MAT(Obj self, Obj list, Obj pos, Obj elm) { + RequireGF2MatRep(SELF_NAME, list); + // check that is mutable RequireMutable("List Assignment", list, "list"); @@ -1939,6 +1973,7 @@ static Obj FuncASS_GF2MAT(Obj self, Obj list, Obj pos, Obj elm) */ static Obj FuncELM_GF2MAT(Obj self, Obj mat, Obj row) { + RequireGF2MatRep(SELF_NAME, mat); UInt r = GetSmallInt(SELF_NAME, row); if (LEN_GF2MAT(mat) < r) { ErrorMayQuit("row index %d exceeds %d, the number of rows", r, @@ -1955,6 +1990,7 @@ static Obj FuncELM_GF2MAT(Obj self, Obj mat, Obj row) */ static Obj FuncSWAP_ROWS_GF2MAT(Obj self, Obj mat, Obj row1, Obj row2) { + RequireGF2MatRep(SELF_NAME, mat); RequireMutable(SELF_NAME, mat, "mat"); UInt r1 = GetSmallInt(SELF_NAME, row1); @@ -1984,6 +2020,7 @@ static Obj FuncSWAP_ROWS_GF2MAT(Obj self, Obj mat, Obj row1, Obj row2) */ static Obj FuncSWAP_COLS_GF2MAT(Obj self, Obj mat, Obj col1, Obj col2) { + RequireGF2MatRep(SELF_NAME, mat); UInt c1 = GetSmallInt(SELF_NAME, col1); UInt c2 = GetSmallInt(SELF_NAME, col2); UInt m = LEN_GF2MAT(mat); @@ -2032,6 +2069,8 @@ static Obj FuncSWAP_COLS_GF2MAT(Obj self, Obj mat, Obj col1, Obj col2) */ static Obj FuncUNB_GF2VEC(Obj self, Obj list, Obj pos) { + RequireGF2VecRep(SELF_NAME, list); + // check that is mutable RequireMutable("List Unbind", list, "vector"); @@ -2069,6 +2108,8 @@ static Obj FuncUNB_GF2VEC(Obj self, Obj list, Obj pos) */ static Obj FuncUNB_GF2MAT(Obj self, Obj list, Obj pos) { + RequireGF2MatRep(SELF_NAME, list); + // check that is mutable RequireMutable("List Unbind", list, "matrix"); @@ -2108,6 +2149,8 @@ static Obj FuncZERO_GF2VEC(Obj self, Obj mat) Obj zero; UInt len; + RequireGF2VecRep(SELF_NAME, mat); + // create a new GF2 vector len = LEN_GF2VEC(mat); NEW_GF2VEC(zero, TYPE_LIST_GF2VEC, len); @@ -2141,6 +2184,8 @@ static Obj FuncINV_GF2MAT_MUTABLE(Obj self, Obj mat) { UInt len; + RequireGF2MatRep(SELF_NAME, mat); + len = LEN_GF2MAT(mat); if (len != 0) { if (len != LEN_GF2VEC(ELM_GF2MAT(mat, 1))) { @@ -2162,6 +2207,8 @@ static Obj FuncINV_GF2MAT_SAME_MUTABILITY(Obj self, Obj mat) { UInt len; + RequireGF2MatRep(SELF_NAME, mat); + len = LEN_GF2MAT(mat); if (len != 0) { if (len != LEN_GF2VEC(ELM_GF2MAT(mat, 1))) { @@ -2183,6 +2230,8 @@ static Obj FuncINV_GF2MAT_IMMUTABLE(Obj self, Obj mat) { UInt len; + RequireGF2MatRep(SELF_NAME, mat); + len = LEN_GF2MAT(mat); if (len != 0) { if (len != LEN_GF2VEC(ELM_GF2MAT(mat, 1))) { @@ -2203,6 +2252,7 @@ static Obj FuncINV_PLIST_GF2VECS_DESTRUCTIVE(Obj self, Obj list) { UInt len, i; Obj row; + RequirePlainList(SELF_NAME, list); len = LEN_PLIST(list); for (i = 1; i <= len; i++) { row = ELM_PLIST(list, i); @@ -2242,6 +2292,9 @@ static Obj FuncSUM_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) Obj sum; // sum, result UInt ll, lr; + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); + ll = LEN_GF2VEC(vl); lr = LEN_GF2VEC(vr); @@ -2269,6 +2322,9 @@ static Obj FuncSUM_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) */ static Obj FuncMULT_VECTOR_GF2VECS_2(Obj self, Obj vl, Obj mul) { + RequireGF2VecRep(SELF_NAME, vl); + RequireFFE(SELF_NAME, mul); + if (EQ(mul, GF2One)) return (Obj)0; else if (EQ(mul, GF2Zero)) { @@ -2289,6 +2345,8 @@ static Obj FuncMULT_VECTOR_GF2VECS_2(Obj self, Obj vl, Obj mul) */ static Obj FuncPROD_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) { + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); return ProdGF2VecGF2Vec(vl, vr); } @@ -2305,6 +2363,8 @@ static Obj FuncPROD_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) */ static Obj FuncPROD_GF2VEC_GF2MAT(Obj self, Obj vl, Obj vr) { + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2MatRep(SELF_NAME, vr); return ProdGF2VecGF2Mat(vl, vr); } @@ -2320,6 +2380,8 @@ static Obj FuncPROD_GF2VEC_GF2MAT(Obj self, Obj vl, Obj vr) */ static Obj FuncPROD_GF2MAT_GF2MAT(Obj self, Obj ml, Obj mr) { + RequireGF2MatRep(SELF_NAME, ml); + RequireGF2MatRep(SELF_NAME, mr); UInt lenl = LEN_GF2MAT(ml); UInt lenm; if (lenl >= 128) { @@ -2344,6 +2406,8 @@ static Obj FuncPROD_GF2MAT_GF2MAT(Obj self, Obj ml, Obj mr) */ static Obj FuncPROD_GF2MAT_GF2MAT_SIMPLE(Obj self, Obj ml, Obj mr) { + RequireGF2MatRep(SELF_NAME, ml); + RequireGF2MatRep(SELF_NAME, mr); return ProdGF2MatGF2MatSimple(ml, mr); } @@ -2362,6 +2426,10 @@ static Obj FuncPROD_GF2MAT_GF2MAT_SIMPLE(Obj self, Obj ml, Obj mr) static Obj FuncPROD_GF2MAT_GF2MAT_ADVANCED( Obj self, Obj ml, Obj mr, Obj greaselevel, Obj blocksize) { + RequireGF2MatRep(SELF_NAME, ml); + RequireGF2MatRep(SELF_NAME, mr); + RequireSmallInt(SELF_NAME, greaselevel); + RequireSmallInt(SELF_NAME, blocksize); return ProdGF2MatGF2MatAdvanced(ml, mr, INT_INTOBJ(greaselevel), INT_INTOBJ(blocksize)); } @@ -2379,6 +2447,8 @@ static Obj FuncPROD_GF2MAT_GF2MAT_ADVANCED( */ static Obj FuncPROD_GF2MAT_GF2VEC(Obj self, Obj vl, Obj vr) { + RequireGF2MatRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); return ProdGF2MatGF2Vec(vl, vr); } @@ -2389,6 +2459,10 @@ static Obj FuncPROD_GF2MAT_GF2VEC(Obj self, Obj vl, Obj vr) */ static Obj FuncADDCOEFFS_GF2VEC_GF2VEC_MULT(Obj self, Obj vl, Obj vr, Obj mul) { + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); + RequireFFE(SELF_NAME, mul); + // do nothing if is zero if (EQ(mul, GF2Zero)) { return INTOBJ_INT(RightMostOneGF2Vec(vl)); @@ -2409,6 +2483,8 @@ static Obj FuncADDCOEFFS_GF2VEC_GF2VEC_MULT(Obj self, Obj vl, Obj vr, Obj mul) */ static Obj FuncADDCOEFFS_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) { + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); return AddCoeffsGF2VecGF2Vec(vl, vr); } @@ -2425,6 +2501,8 @@ static Obj FuncSHRINKCOEFFS_GF2VEC(Obj self, Obj vec) UInt * ptr; UInt off; + RequireGF2VecRep(SELF_NAME, vec); + // get length and number of blocks len = LEN_GF2VEC(vec); if (len == 0) { @@ -2522,11 +2600,14 @@ static UInt PositionNonZeroGF2Vec(Obj vec, UInt from) static Obj FuncPOSITION_NONZERO_GF2VEC(Obj self, Obj vec, Obj zero) { + RequireGF2VecRep(SELF_NAME, vec); return INTOBJ_INT(PositionNonZeroGF2Vec(vec, 0)); } static Obj FuncPOSITION_NONZERO_GF2VEC3(Obj self, Obj vec, Obj zero, Obj from) { + RequireGF2VecRep(SELF_NAME, vec); + RequireNonnegativeSmallInt(SELF_NAME, from); return INTOBJ_INT(PositionNonZeroGF2Vec(vec, INT_INTOBJ(from))); } @@ -2538,12 +2619,8 @@ static Obj FuncCOPY_SECTION_GF2VECS( Int ito = GetPositiveSmallInt(SELF_NAME, to); Int ihowmany = GetSmallInt(SELF_NAME, howmany); - if (!IS_GF2VEC_REP(src)) { - RequireArgument(SELF_NAME, src, "must be a GF2 vector"); - } - if (!IS_GF2VEC_REP(dest)) { - RequireArgument(SELF_NAME, dest, "must be a GF2 vector"); - } + RequireGF2VecRep(SELF_NAME, src); + RequireGF2VecRep(SELF_NAME, dest); UInt lens = LEN_GF2VEC(src); UInt lend = LEN_GF2VEC(dest); @@ -2566,6 +2643,9 @@ static Obj FuncCOPY_SECTION_GF2VECS( static Obj FuncAPPEND_GF2VEC(Obj self, Obj vecl, Obj vecr) { UInt lenl, lenr; + RequireGF2VecRep(SELF_NAME, vecl); + RequireGF2VecRep(SELF_NAME, vecr); + RequireMutable(SELF_NAME, vecl, "vector"); lenl = LEN_GF2VEC(vecl); lenr = LEN_GF2VEC(vecr); if (True == DoFilter(IsLockedRepresentationVector, vecl) && lenr > 0) { @@ -2586,6 +2666,7 @@ static Obj FuncAPPEND_GF2VEC(Obj self, Obj vecl, Obj vecr) static Obj FuncSHALLOWCOPY_GF2VEC(Obj self, Obj vec) { + RequireGF2VecRep(SELF_NAME, vec); return ShallowCopyVecGF2(vec); } @@ -2603,6 +2684,8 @@ static Obj FuncSUM_GF2MAT_GF2MAT(Obj self, Obj matl, Obj matr) Obj vl, vr, sv; UInt i; Obj rtype; + RequireGF2MatRep(SELF_NAME, matl); + RequireGF2MatRep(SELF_NAME, matr); ll = LEN_GF2MAT(matl); lr = LEN_GF2MAT(matr); if (ll > lr) { @@ -2695,10 +2778,11 @@ static Obj FuncTRANSPOSED_GF2MAT(Obj self, Obj mat) UInt imod, nrb, nstart; UInt i, j, k, n; - if (TNUM_OBJ(mat) != T_POSOBJ) { - ErrorMayQuit("TRANSPOSED_GF2MAT: Need compressed matrix over GF(2)", - 0, 0); - } + RequireGF2MatRep(SELF_NAME, mat); + + if (LEN_GF2MAT(mat) == 0) + return TRY_NEXT_METHOD; + // type for mat typ = TYPE_LIST_GF2MAT; @@ -2780,6 +2864,7 @@ static Obj FuncNUMBER_GF2VEC(Obj self, Obj vec) Obj zahl; // the long number UInt * num2; mp_limb_t * vp; + RequireGF2VecRep(SELF_NAME, vec); len = LEN_GF2VEC(vec); if (len == 0) return INTOBJ_INT(1); @@ -2842,6 +2927,8 @@ static Obj FuncNUMBER_GF2VEC(Obj self, Obj vec) */ static Obj FuncLT_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) { + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); return (Cmp_GF2VEC_GF2VEC(vl, vr) < 0) ? True : False; } @@ -2876,6 +2963,8 @@ static Int Cmp_GF2MAT_GF2MAT(Obj ml, Obj mr) static Obj FuncEQ_GF2MAT_GF2MAT(Obj self, Obj ml, Obj mr) { + RequireGF2MatRep(SELF_NAME, ml); + RequireGF2MatRep(SELF_NAME, mr); if (ELM_PLIST(ml, 1) != ELM_PLIST(mr, 1)) return False; return (0 == Cmp_GF2MAT_GF2MAT(ml, mr)) ? True : False; @@ -2888,6 +2977,8 @@ static Obj FuncEQ_GF2MAT_GF2MAT(Obj self, Obj ml, Obj mr) static Obj FuncLT_GF2MAT_GF2MAT(Obj self, Obj ml, Obj mr) { + RequireGF2MatRep(SELF_NAME, ml); + RequireGF2MatRep(SELF_NAME, mr); return (Cmp_GF2MAT_GF2MAT(ml, mr) < 0) ? True : False; } @@ -2931,6 +3022,8 @@ static Obj FuncDIST_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) UInt * ptL; // bit field of UInt * ptR; // bit field of UInt * end; // pointer used to zero out end bit + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); // get and check the length len = LEN_GF2VEC(vl); @@ -2938,6 +3031,8 @@ static Obj FuncDIST_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) ErrorMayQuit("DIST_GF2VEC_GF2VEC: vectors must have the same length", 0, 0); } + if (len == 0) + return INTOBJ_INT(0); // calculate the offsets ptL = BLOCKS_GF2VEC(vl); @@ -3010,6 +3105,10 @@ static Obj FuncDIST_VEC_CLOS_VEC( Obj sum; // sum vector UInt len; + RequirePlainList(SELF_NAME, veclis); + RequireGF2VecRep(SELF_NAME, vec); + RequirePlainList(SELF_NAME, d); + len = LEN_GF2VEC(vec); // get space for sum vector @@ -3123,6 +3222,9 @@ static Obj FuncA_CLOS_VEC( Obj best; // best vector UInt len; + RequirePlainList(SELF_NAME, veclis); + RequireGF2VecRep(SELF_NAME, vec); + len = LEN_GF2VEC(vec); RequireNonnegativeSmallInt(SELF_NAME, cnt); @@ -3155,6 +3257,9 @@ static Obj FuncA_CLOS_VEC_COORDS( Obj res; // length 2 plist for results UInt len, len2, i; + RequirePlainList(SELF_NAME, veclis); + RequireGF2VecRep(SELF_NAME, vec); + len = LEN_GF2VEC(vec); len2 = LEN_PLIST(veclis); @@ -3293,6 +3398,7 @@ static Obj FuncCOSET_LEADERS_INNER_GF2( static Obj FuncRIGHTMOST_NONZERO_GF2VEC(Obj self, Obj vec) { + RequireGF2VecRep(SELF_NAME, vec); return INTOBJ_INT(RightMostOneGF2Vec(vec)); } @@ -3362,6 +3468,7 @@ static void ResizeGF2Vec(Obj vec, UInt newlen) static Obj FuncRESIZE_GF2VEC(Obj self, Obj vec, Obj newlen) { + RequireGF2VecRep(SELF_NAME, vec); RequireMutable(SELF_NAME, vec, "vector"); RequireNonnegativeSmallInt(SELF_NAME, newlen); ResizeGF2Vec(vec, INT_INTOBJ(newlen)); @@ -3421,6 +3528,7 @@ static void ShiftLeftGF2Vec(Obj vec, UInt amount) static Obj FuncSHIFT_LEFT_GF2VEC(Obj self, Obj vec, Obj amount) { + RequireGF2VecRep(SELF_NAME, vec); RequireMutable(SELF_NAME, vec, "vector"); RequireNonnegativeSmallInt(SELF_NAME, amount); ShiftLeftGF2Vec(vec, INT_INTOBJ(amount)); @@ -3484,8 +3592,10 @@ static void ShiftRightGF2Vec(Obj vec, UInt amount) static Obj FuncSHIFT_RIGHT_GF2VEC(Obj self, Obj vec, Obj amount, Obj zero) { + RequireGF2VecRep(SELF_NAME, vec); RequireMutable(SELF_NAME, vec, "vector"); RequireNonnegativeSmallInt(SELF_NAME, amount); + RequireFFE(SELF_NAME, zero); ShiftRightGF2Vec(vec, INT_INTOBJ(amount)); return (Obj)0; } @@ -3546,6 +3656,9 @@ static void AddShiftedVecGF2VecGF2(Obj vec1, Obj vec2, UInt len2, UInt off) static Obj FuncADD_GF2VEC_GF2VEC_SHIFTED(Obj self, Obj vec1, Obj vec2, Obj len2, Obj off) { + RequireGF2VecRep(SELF_NAME, vec1); + RequireGF2VecRep(SELF_NAME, vec2); + RequireMutable(SELF_NAME, vec1, "vector"); RequireNonnegativeSmallInt(SELF_NAME, off); RequireNonnegativeSmallInt(SELF_NAME, len2); Int off1 = INT_INTOBJ(off); @@ -3619,8 +3732,8 @@ FuncPROD_COEFFS_GF2VEC(Obj self, Obj vec1, Obj len1, Obj vec2, Obj len2) Obj prod; UInt last; - RequireSmallInt(SELF_NAME, len1); - RequireSmallInt(SELF_NAME, len2); + RequireNonnegativeSmallInt(SELF_NAME, len1); + RequireNonnegativeSmallInt(SELF_NAME, len2); len2a = INT_INTOBJ(len2); if (len2a > LEN_GF2VEC(vec2)) ErrorMayQuit("PROD_COEFFS_GF2VEC: must not be more than the " @@ -3686,6 +3799,9 @@ FuncREDUCE_COEFFS_GF2VEC(Obj self, Obj vec1, Obj len1, Obj vec2, Obj len2) { UInt last; Int len2a; + RequireGF2VecRep(SELF_NAME, vec1); + RequireGF2VecRep(SELF_NAME, vec2); + RequireMutable(SELF_NAME, vec1, "vector"); RequireNonnegativeSmallInt(SELF_NAME, len1); RequireNonnegativeSmallInt(SELF_NAME, len2); if (INT_INTOBJ(len1) > LEN_GF2VEC(vec1)) @@ -3729,10 +3845,13 @@ static Obj FuncQUOTREM_COEFFS_GF2VEC(Obj self, Obj vec1, Obj len1, Obj vec2, Obj len2) { Int len2a; - Int len1a = INT_INTOBJ(len1); + Int len1a; Obj quotv, remv, ret; + RequireGF2VecRep(SELF_NAME, vec1); + RequireGF2VecRep(SELF_NAME, vec2); RequireNonnegativeSmallInt(SELF_NAME, len1); RequireNonnegativeSmallInt(SELF_NAME, len2); + len1a = INT_INTOBJ(len1); if (INT_INTOBJ(len1) > LEN_GF2VEC(vec1)) ErrorMayQuit("QuotremCoeffs: given length of left argt " "(%d)\nis longer than the argt (%d)", @@ -3791,6 +3910,7 @@ static Obj FuncSEMIECHELON_LIST_GF2VECS(Obj self, Obj mat) UInt i, len; UInt width; Obj row; + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) return TRY_NEXT_METHOD; @@ -3825,6 +3945,7 @@ static Obj FuncSEMIECHELON_LIST_GF2VECS_TRANSFORMATIONS(Obj self, Obj mat) UInt i, len; UInt width; Obj row; + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) return TRY_NEXT_METHOD; @@ -3855,6 +3976,7 @@ static Obj FuncTRIANGULIZE_LIST_GF2VECS(Obj self, Obj mat) UInt i, len; UInt width; Obj row; + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) return TRY_NEXT_METHOD; @@ -3886,6 +4008,7 @@ static Obj FuncRANK_LIST_GF2VECS(Obj self, Obj mat) UInt i, len; UInt width; Obj row; + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) return TRY_NEXT_METHOD; @@ -3916,6 +4039,7 @@ static Obj FuncDETERMINANT_LIST_GF2VECS(Obj self, Obj mat) UInt i, len; UInt width; Obj row; + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) return TRY_NEXT_METHOD; @@ -3948,6 +4072,9 @@ static Obj FuncKRONECKERPRODUCT_GF2MAT_GF2MAT(Obj self, Obj matl, Obj matr) UInt * data; const UInt * datar; + RequireGF2MatRep(SELF_NAME, matl); + RequireGF2MatRep(SELF_NAME, matr); + nrowl = LEN_GF2MAT(matl); nrowr = LEN_GF2MAT(matr); nrowp = nrowl * nrowr; @@ -4036,6 +4163,7 @@ static Obj FuncKRONECKERPRODUCT_GF2MAT_GF2MAT(Obj self, Obj matl, Obj matr) */ static Obj FuncMAT_ELM_GF2MAT(Obj self, Obj mat, Obj row, Obj col) { + RequireGF2MatRep(SELF_NAME, mat); UInt r = GetPositiveSmallInt(SELF_NAME, row); UInt c = GetPositiveSmallInt(SELF_NAME, col); @@ -4063,6 +4191,7 @@ static Obj FuncMAT_ELM_GF2MAT(Obj self, Obj mat, Obj row, Obj col) static Obj FuncSET_MAT_ELM_GF2MAT(Obj self, Obj mat, Obj row, Obj col, Obj elm) { + RequireGF2MatRep(SELF_NAME, mat); UInt r = GetPositiveSmallInt(SELF_NAME, row); UInt c = GetPositiveSmallInt(SELF_NAME, col); @@ -4203,6 +4332,7 @@ static Int InitKernel(StructInitInfo * module) InitCopyGVar("TYPE_LIST_GF2VEC_LOCKED", &TYPE_LIST_GF2VEC_LOCKED); ImportFuncFromLibrary("IsGF2VectorRep", &IsGF2VectorRep); + ImportFuncFromLibrary("IsGF2MatrixRep", &IsGF2MatrixRep); InitCopyGVar("TYPE_LIST_GF2MAT", &TYPE_LIST_GF2MAT); InitCopyGVar("TYPE_LIST_GF2MAT_IMM", &TYPE_LIST_GF2MAT_IMM); diff --git a/src/vecgf2.h b/src/vecgf2.h index ddeac8639a..8471236efd 100644 --- a/src/vecgf2.h +++ b/src/vecgf2.h @@ -20,6 +20,13 @@ #define IS_GF2VEC_REP(obj) \ (TNUM_OBJ(obj) == T_DATOBJ && DoFilter(IsGF2VectorRep, obj) == True) +/**************************************************************************** +** +*F IS_GF2MAT_REP( ) . . . . . . check that is in GF2 matrix rep +*/ +#define IS_GF2MAT_REP(obj) \ + (TNUM_OBJ(obj) == T_POSOBJ && DoFilter(IsGF2MatrixRep, obj) == True) + /**************************************************************************** ** @@ -234,6 +241,7 @@ extern Obj TYPE_LIST_GF2MAT_IMM; extern Obj IsGF2VectorRep; +extern Obj IsGF2MatrixRep; Obj ShallowCopyVecGF2(Obj vec); diff --git a/tst/testinstall/kernel/vec8bit.tst b/tst/testinstall/kernel/vec8bit.tst index 6e951a3ef0..b9fe3df7e4 100644 --- a/tst/testinstall/kernel/vec8bit.tst +++ b/tst/testinstall/kernel/vec8bit.tst @@ -2,11 +2,1198 @@ # Tests for functions defined in src/vec8bit.c # gap> START_TEST("kernel/vec8bit.tst"); +gap> q := 5;; +gap> z := 0*Z(q);; +gap> o := Z(q)^0;; +gap> t := Z(q);; +gap> V8 := function(list) +> local v; +> v := ShallowCopy(list); +> CONV_VEC8BIT(v, q); +> return v; +> end;; +gap> M8 := function(rows) +> local m, i; +> m := List(rows, ShallowCopy); +> for i in [1 .. Length(m)] do +> CONV_VEC8BIT(m[i], q); +> od; +> CONV_MAT8BIT(m, q); +> return m; +> end;; +gap> IM8 := function(rows) +> local m; +> m := M8(rows); +> MakeImmutable(m); +> return m; +> end;; +gap> ZeroRowMat8 := function() +> local m; +> m := []; +> CONV_MAT8BIT(m, q); +> return m; +> end;; +gap> Mx08 := n -> M8(List([1 .. n], i -> []));; +gap> Veclis8 := function(rows) +> local f, fdi, fdip, veclis, row, mults, j, mult; +> f := AsSSortedList(GF(q)); +> fdi := []; +> for j in [2 .. Length(f)] do +> fdi[j - 1] := f[j] - f[j - 1]; +> od; +> Add(fdi, -Last(f)); +> fdip := List(fdi, x -> Position(fdi, x)); +> veclis := []; +> for row in rows do +> mults := []; +> mults[Length(fdi) + 1] := false; +> for j in [1 .. Length(fdi)] do +> if fdip[j] < j then +> mult := mults[fdip[j]]; +> else +> mult := fdi[j] * row; +> fi; +> mults[j] := mult; +> od; +> Add(veclis, mults); +> od; +> return veclis; +> end;; +gap> empty := V8([]);; +gap> one := V8([o]);; +gap> oneZero := V8([z]);; +gap> pair := V8([o, t]);; +gap> pair2 := V8([t, o]);; +gap> f5 := AsSSortedList(GF(q));; # +# CONV_VEC8BIT +# +gap> v := [];; CONV_VEC8BIT(v, q); v; +< mutable compressed vector length 0 over GF(5) > + +# bad arguments +gap> CONV_VEC8BIT(fail, q); +Error, CONV_VEC8BIT: must be a small list (not the value 'fail') +gap> CONV_VEC8BIT(v, fail); +Error, CONV_VEC8BIT: must be a positive small integer (not the value 'fail\ +') + +# +# COPY_VEC8BIT +# +gap> v := [];; w := COPY_VEC8BIT(v, q); v; +< mutable compressed vector length 0 over GF(5) > +[ ] + +# bad arguments +gap> COPY_VEC8BIT(fail, q); +Error, COPY_VEC8BIT: must be a small list (not the value 'fail') +gap> COPY_VEC8BIT(v, fail); +Error, COPY_VEC8BIT: must be a positive small integer (not the value 'fail\ +') + +# +# PLAIN_VEC8BIT +# +gap> v := V8([]);; PLAIN_VEC8BIT(v);; IsPlistRep(v); Length(v); +true +0 + +# bad arguments +gap> PLAIN_VEC8BIT(fail); +Error, PLAIN_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fa\ +il') + +# +# LEN_VEC8BIT +# +gap> LEN_VEC8BIT(empty); +0 +gap> LEN_VEC8BIT(pair); +2 + +# bad arguments +gap> LEN_VEC8BIT(fail); +Error, LEN_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fail\ +') + +# +# ELM0_VEC8BIT +# +gap> ELM0_VEC8BIT(empty, 1); +fail +gap> ELM0_VEC8BIT(one, 1); +Z(5)^0 + +# bad arguments +gap> ELM0_VEC8BIT(fail, 1); +Error, ELM0_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fai\ +l') +gap> ELM0_VEC8BIT(empty, fail); +Error, ELM0_VEC8BIT: must be a positive small integer (not the value 'fa\ +il') + +# +# ELM_VEC8BIT +# +gap> ELM_VEC8BIT(one, 1); +Z(5)^0 + +# bad arguments +gap> ELM_VEC8BIT(fail, 1); +Error, ELM_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fail\ +') +gap> ELM_VEC8BIT(one, fail); +Error, ELM_VEC8BIT: must be a positive small integer (not the value 'fai\ +l') + +# +# ELMS_VEC8BIT +# +gap> ELMS_VEC8BIT(empty, []) = empty; +true +gap> ELMS_VEC8BIT(pair, [2]); # = V8([t])); +[ Z(5) ] + +# bad arguments +gap> ELMS_VEC8BIT(fail, []); +Error, ELMS_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fai\ +l') +gap> ELMS_VEC8BIT(empty, fail); +Error, ELMS_VEC8BIT: must be a plain list (not the value 'fail') + +# +# ELMS_VEC8BIT_RANGE +# +gap> ELMS_VEC8BIT_RANGE(one, [1 .. 1]); +Error, ELMS_VEC8BIT_RANGE: must be a range (not a strictly-sorted plai\ +n list of cyclotomics) +gap> ELMS_VEC8BIT_RANGE(pair, [1 .. 2]) = pair; +true + +# bad arguments +gap> ELMS_VEC8BIT_RANGE(fail, [1 .. 1]); +Error, ELMS_VEC8BIT_RANGE: must belong to Is8BitVectorRep (not the valu\ +e 'fail') +gap> ELMS_VEC8BIT_RANGE(one, fail); +Error, ELMS_VEC8BIT_RANGE: must be a range (not the value 'fail') + +# +# ASS_VEC8BIT +# +gap> v := V8([]);; ASS_VEC8BIT(v, 1, z);; v = V8([z]); +true +gap> v := [Z(23), Z(23)];; ConvertToVectorRep(v);; ASS_VEC8BIT(v, 1, Z(23^5));; +gap> Is8BitVectorRep(v); +false +gap> v; +[ z, Z(23) ] + +# bad arguments +gap> v := V8([z, z]);; +gap> ASS_VEC8BIT(fail, 1, z); +Error, ASS_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fail\ +') +gap> ASS_VEC8BIT(v, fail, z); +Error, ASS_VEC8BIT: must be a positive small integer (not the value 'fai\ +l') +gap> ASS_VEC8BIT(v, 1, fail);; +gap> IsPlistRep(v); +true +gap> v; +[ fail, 0*Z(5) ] + +# +# UNB_VEC8BIT +# +gap> v := V8([o]);; UNB_VEC8BIT(v, 1);; v = empty; +true + +# bad arguments +gap> UNB_VEC8BIT(fail, 1); +Error, UNB_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fail\ +') +gap> UNB_VEC8BIT(v, fail); +Error, UNB_VEC8BIT: must be a positive small integer (not the value 'fai\ +l') + +# +# Q_VEC8BIT +# +gap> Q_VEC8BIT(empty); +5 + +# bad arguments +gap> Q_VEC8BIT(fail); +Error, Q_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fail') + +# +# SHALLOWCOPY_VEC8BIT +# +gap> v := SHALLOWCOPY_VEC8BIT(empty);; v = empty and not IsIdenticalObj(v, empty); +true + +# bad arguments +gap> SHALLOWCOPY_VEC8BIT(fail); +Error, SHALLOWCOPY_VEC8BIT: must belong to Is8BitVectorRep (not the val\ +ue 'fail') + +# +# SUM_VEC8BIT_VEC8BIT +# +gap> SUM_VEC8BIT_VEC8BIT(empty, empty); +< mutable compressed vector length 0 over GF(5) > +gap> SUM_VEC8BIT_VEC8BIT(one, oneZero); +[ Z(5)^0 ] + +# bad arguments +gap> SUM_VEC8BIT_VEC8BIT(fail, empty); +Error, SUM_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the value\ + 'fail') +gap> SUM_VEC8BIT_VEC8BIT(empty, fail); +Error, SUM_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the value\ + 'fail') + +# +# DIFF_VEC8BIT_VEC8BIT +# +gap> DIFF_VEC8BIT_VEC8BIT(empty, empty); +< mutable compressed vector length 0 over GF(5) > +gap> DIFF_VEC8BIT_VEC8BIT(one, oneZero); +[ Z(5)^0 ] + +# bad arguments +gap> DIFF_VEC8BIT_VEC8BIT(fail, empty); +Error, DIFF_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the valu\ +e 'fail') +gap> DIFF_VEC8BIT_VEC8BIT(empty, fail); +Error, DIFF_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the valu\ +e 'fail') + +# +# PROD_VEC8BIT_FFE +# +gap> PROD_VEC8BIT_FFE(empty, o); +< mutable compressed vector length 0 over GF(5) > +gap> PROD_VEC8BIT_FFE(one, z); +[ 0*Z(5) ] + +# bad arguments +gap> PROD_VEC8BIT_FFE(fail, o); +Error, PROD_VEC8BIT_FFE: must belong to Is8BitVectorRep (not the value '\ +fail') +gap> PROD_VEC8BIT_FFE(empty, fail); +Error, PROD_VEC8BIT_FFE: must be a finite field element (not the value '\ +fail') + +# +# PROD_FFE_VEC8BIT +# +gap> PROD_FFE_VEC8BIT(o, empty); +< mutable compressed vector length 0 over GF(5) > +gap> PROD_FFE_VEC8BIT(z, one); +[ 0*Z(5) ] + +# bad arguments +gap> PROD_FFE_VEC8BIT(fail, empty); +Error, PROD_FFE_VEC8BIT: must be a finite field element (not the value '\ +fail') +gap> PROD_FFE_VEC8BIT(o, fail); +Error, PROD_FFE_VEC8BIT: must belong to Is8BitVectorRep (not the value '\ +fail') + +# +# AINV_VEC8BIT_MUTABLE +# +gap> AINV_VEC8BIT_MUTABLE(empty); +< mutable compressed vector length 0 over GF(5) > +gap> AINV_VEC8BIT_MUTABLE(oneZero); +[ 0*Z(5) ] + +# bad arguments +gap> AINV_VEC8BIT_MUTABLE(fail); +Error, AINV_VEC8BIT_MUTABLE: must belong to Is8BitVectorRep (not the val\ +ue 'fail') + +# +# AINV_VEC8BIT_IMMUTABLE +# +gap> AINV_VEC8BIT_IMMUTABLE(empty); +< immutable compressed vector length 0 over GF(5) > +gap> AINV_VEC8BIT_IMMUTABLE(oneZero); +[ 0*Z(5) ] + +# bad arguments +gap> AINV_VEC8BIT_IMMUTABLE(fail); +Error, AINV_VEC8BIT_IMMUTABLE: must belong to Is8BitVectorRep (not the v\ +alue 'fail') + +# +# AINV_VEC8BIT_SAME_MUTABILITY +# +gap> AINV_VEC8BIT_SAME_MUTABILITY(empty); +< mutable compressed vector length 0 over GF(5) > +gap> AINV_VEC8BIT_SAME_MUTABILITY(oneZero); +[ 0*Z(5) ] + +# bad arguments +gap> AINV_VEC8BIT_SAME_MUTABILITY(fail); +Error, AINV_VEC8BIT_SAME_MUTABILITY: must belong to Is8BitVectorRep (not\ + the value 'fail') + +# +# ZERO_VEC8BIT +# +gap> ZERO_VEC8BIT(empty); +< mutable compressed vector length 0 over GF(5) > +gap> ZERO_VEC8BIT(pair); +[ 0*Z(5), 0*Z(5) ] + +# bad arguments +gap> ZERO_VEC8BIT(fail); +Error, ZERO_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fail\ +') + +# +# ZERO_VEC8BIT_2 +# +gap> ZERO_VEC8BIT_2(q, 0); +< mutable compressed vector length 0 over GF(5) > +gap> ZERO_VEC8BIT_2(q, 2); +[ 0*Z(5), 0*Z(5) ] + +# bad arguments +gap> ZERO_VEC8BIT_2(fail, 0); +Error, ZERO_VEC8BIT_2: must be a positive small integer (not the value 'fa\ +il') +gap> ZERO_VEC8BIT_2(q, fail); +Error, ZERO_VEC8BIT_2: must be a non-negative small integer (not the val\ +ue 'fail') + +# +# EQ_VEC8BIT_VEC8BIT +# +gap> EQ_VEC8BIT_VEC8BIT(empty, empty); +true +gap> EQ_VEC8BIT_VEC8BIT(empty, one); +false + +# bad arguments +gap> EQ_VEC8BIT_VEC8BIT(fail, empty); +Error, EQ_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the value \ +'fail') +gap> EQ_VEC8BIT_VEC8BIT(empty, fail); +Error, EQ_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the value \ +'fail') + +# +# LT_VEC8BIT_VEC8BIT +# +gap> LT_VEC8BIT_VEC8BIT(empty, one); +true +gap> LT_VEC8BIT_VEC8BIT(one, empty); +false + +# bad arguments +gap> LT_VEC8BIT_VEC8BIT(fail, one); +Error, LT_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the value \ +'fail') +gap> LT_VEC8BIT_VEC8BIT(empty, fail); +Error, LT_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the value \ +'fail') + +# +# PROD_VEC8BIT_VEC8BIT +# +gap> PROD_VEC8BIT_VEC8BIT(empty, empty); +0*Z(5) +gap> PROD_VEC8BIT_VEC8BIT(one, one); +Z(5)^0 + +# bad arguments +gap> PROD_VEC8BIT_VEC8BIT(fail, empty); +Error, PROD_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the valu\ +e 'fail') +gap> PROD_VEC8BIT_VEC8BIT(empty, fail); +Error, PROD_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the valu\ +e 'fail') + +# +# DISTANCE_VEC8BIT_VEC8BIT +# +gap> DISTANCE_VEC8BIT_VEC8BIT(empty, empty); +0 +gap> DISTANCE_VEC8BIT_VEC8BIT(one, oneZero); +1 + +# bad arguments +gap> DISTANCE_VEC8BIT_VEC8BIT(fail, empty); +Error, DISTANCE_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the \ +value 'fail') +gap> DISTANCE_VEC8BIT_VEC8BIT(empty, fail); +Error, DISTANCE_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the \ +value 'fail') + +# +# ADD_ROWVECTOR_VEC8BITS_5 +# +gap> v := V8([o, z]);; ADD_ROWVECTOR_VEC8BITS_5(v, V8([z, o]), o, 2, 2);; v = V8([o, o]); +true + +# bad arguments +gap> ADD_ROWVECTOR_VEC8BITS_5(fail, V8([z, o]), o, 2, 2); +Error, ADD_ROWVECTOR_VEC8BITS_5: must belong to Is8BitVectorRep (not the \ +value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_5(v, fail, o, 2, 2); +Error, ADD_ROWVECTOR_VEC8BITS_5: must belong to Is8BitVectorRep (not the \ +value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_5(v, V8([z, o]), fail, 2, 2); +Error, ADD_ROWVECTOR_VEC8BITS_5: must be a finite field element (not the\ + value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_5(v, V8([z, o]), o, fail, 2); +Error, ADD_ROWVECTOR_VEC8BITS_5: must be a positive small integer (not \ +the value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_5(v, V8([z, o]), o, 2, fail); +Error, ADD_ROWVECTOR_VEC8BITS_5: must be a positive small integer (not th\ +e value 'fail') + +# +# ADD_ROWVECTOR_VEC8BITS_3 +# +gap> v := V8([]);; ADD_ROWVECTOR_VEC8BITS_3(v, empty, o);; v = empty; +true + +# bad arguments +gap> ADD_ROWVECTOR_VEC8BITS_3(fail, empty, o); +Error, ADD_ROWVECTOR_VEC8BITS_3: must belong to Is8BitVectorRep (not the \ +value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_3(v, fail, o); +Error, ADD_ROWVECTOR_VEC8BITS_3: must belong to Is8BitVectorRep (not the \ +value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_3(v, empty, fail); +Error, ADD_ROWVECTOR_VEC8BITS_3: must be a finite field element (not the\ + value 'fail') + +# +# ADD_ROWVECTOR_VEC8BITS_2 +# +gap> v := V8([]);; ADD_ROWVECTOR_VEC8BITS_2(v, empty);; v = empty; +true + +# bad arguments +gap> ADD_ROWVECTOR_VEC8BITS_2(fail, empty); +Error, ADD_ROWVECTOR_VEC8BITS_2: must belong to Is8BitVectorRep (not the \ +value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_2(v, fail); +Error, ADD_ROWVECTOR_VEC8BITS_2: must belong to Is8BitVectorRep (not the \ +value 'fail') + +# +# MULT_VECTOR_VEC8BITS +# +gap> v := V8([]);; MULT_VECTOR_VEC8BITS(v, o);; v = empty; +true + +# bad arguments +gap> MULT_VECTOR_VEC8BITS(fail, o); +Error, MULT_VECTOR_VEC8BITS: must belong to Is8BitVectorRep (not the val\ +ue 'fail') +gap> MULT_VECTOR_VEC8BITS(v, fail); +Error, MULT_VECTOR_VEC8BITS: must be a finite field element (not the val\ +ue 'fail') + +# +# POSITION_NONZERO_VEC8BIT +# +gap> POSITION_NONZERO_VEC8BIT(empty, z); +1 +gap> POSITION_NONZERO_VEC8BIT(one, z); +1 + +# bad arguments +gap> POSITION_NONZERO_VEC8BIT(fail, z); +Error, POSITION_NONZERO_VEC8BIT: must belong to Is8BitVectorRep (not th\ +e value 'fail') +gap> POSITION_NONZERO_VEC8BIT(empty, fail); +1 + +# +# POSITION_NONZERO_VEC8BIT3 +# +gap> POSITION_NONZERO_VEC8BIT3(empty, z, 1); +1 +gap> POSITION_NONZERO_VEC8BIT3(V8([z, o]), z, 2); +3 + +# bad arguments +gap> POSITION_NONZERO_VEC8BIT3(fail, z, 1); +Error, POSITION_NONZERO_VEC8BIT3: must belong to Is8BitVectorRep (not t\ +he value 'fail') +gap> POSITION_NONZERO_VEC8BIT3(empty, fail, 1); +1 +gap> POSITION_NONZERO_VEC8BIT3(empty, z, fail); +Error, POSITION_NONZERO_VEC8BIT3: must be a non-negative small integer \ +(not the value 'fail') + +# +# APPEND_VEC8BIT +# +gap> v := V8([]);; APPEND_VEC8BIT(v, one);; v = one; +true + +# bad arguments +gap> APPEND_VEC8BIT(fail, one); +Error, APPEND_VEC8BIT: must belong to Is8BitVectorRep (not the value 'f\ +ail') +gap> APPEND_VEC8BIT(v, fail); +Error, APPEND_VEC8BIT: must belong to Is8BitVectorRep (not the value 'f\ +ail') + +# +# NUMBER_VEC8BIT +# +gap> NUMBER_VEC8BIT(empty); +1 +gap> NUMBER_VEC8BIT(one); +1 + +# bad arguments +gap> NUMBER_VEC8BIT(fail); +Error, NUMBER_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fa\ +il') + +# +# PROD_VEC8BIT_MATRIX +# +gap> PROD_VEC8BIT_MATRIX(one, [fail]); +"TRY_NEXT_METHOD" +gap> PROD_VEC8BIT_MATRIX(one, [one]); +[ Z(5)^0 ] + +# bad arguments +gap> PROD_VEC8BIT_MATRIX(fail, [fail]); +Error, PROD_VEC8BIT_MATRIX: must belong to Is8BitVectorRep (not the valu\ +e 'fail') +gap> PROD_VEC8BIT_MATRIX(one, fail); +Error, PROD_VEC8BIT_MATRIX: must be a plain list (not the value 'fail') + +# +# CONV_MAT8BIT +# +gap> m := [V8([]), V8([])];; CONV_MAT8BIT(m, q);; EQ_MAT8BIT_MAT8BIT(m, Mx08(2)); +true + +# bad arguments +gap> CONV_MAT8BIT(fail, q); +Error, CONV_MAT8BIT: must be a plain list (not the value 'fail') +gap> CONV_MAT8BIT(m, fail); +Error, CONV_MAT8BIT: must be a plain list (not a positional object) + +# +# PLAIN_MAT8BIT +# +gap> m := Mx08(2);; PLAIN_MAT8BIT(m);; IsPlistRep(m) and m = [[], []]; +true + +# bad arguments +gap> PLAIN_MAT8BIT(fail); +Error, PLAIN_MAT8BIT: must belong to Is8BitMatrixRep (not the value 'fai\ +l') + +# +# PROD_VEC8BIT_MAT8BIT +# +gap> PROD_VEC8BIT_MAT8BIT(empty, ZeroRowMat8()); +Error, PROD_VEC8BIT_MAT8BIT: compressed 8bit matrices with empty rows are not \ +supported +gap> PROD_VEC8BIT_MAT8BIT(empty, Mx08(2)); +< mutable compressed vector length 0 over GF(5) > + +# bad arguments +gap> PROD_VEC8BIT_MAT8BIT(fail, ZeroRowMat8()); +Error, PROD_VEC8BIT_MAT8BIT: must belong to Is8BitVectorRep (not the val\ +ue 'fail') +gap> PROD_VEC8BIT_MAT8BIT(empty, fail); +Error, PROD_VEC8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the val\ +ue 'fail') + +# +# PROD_MAT8BIT_VEC8BIT +# +gap> PROD_MAT8BIT_VEC8BIT(ZeroRowMat8(), empty); +Error, PROD_MAT8BIT_VEC8BIT: compressed 8bit matrices with empty rows are not \ +supported +gap> PROD_MAT8BIT_VEC8BIT(Mx08(2), empty); +[ 0*Z(5), 0*Z(5) ] + +# bad arguments +gap> PROD_MAT8BIT_VEC8BIT(fail, empty); +Error, PROD_MAT8BIT_VEC8BIT: must belong to Is8BitMatrixRep (not the val\ +ue 'fail') +gap> PROD_MAT8BIT_VEC8BIT(ZeroRowMat8(), fail); +Error, PROD_MAT8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the val\ +ue 'fail') + +# +# PROD_MAT8BIT_MAT8BIT +# +gap> PROD_MAT8BIT_MAT8BIT(ZeroRowMat8(), ZeroRowMat8()); +Error, PROD_MAT8BIT_MAT8BIT: compressed 8bit matrices with empty rows are not \ +supported +gap> PROD_MAT8BIT_MAT8BIT(M8([[o], [z]]), Mx08(1)) = Mx08(2); +true + +# bad arguments +gap> PROD_MAT8BIT_MAT8BIT(fail, ZeroRowMat8()); +Error, PROD_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the va\ +lue 'fail') +gap> PROD_MAT8BIT_MAT8BIT(ZeroRowMat8(), fail); +Error, PROD_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the va\ +lue 'fail') + +# +# INV_MAT8BIT_MUTABLE +# +gap> INV_MAT8BIT_MUTABLE(ZeroRowMat8()); +Error, INV_MAT8BIT_MUTABLE: compressed 8bit matrices with empty rows are not s\ +upported +gap> INV_MAT8BIT_MUTABLE(M8([[o]])) = M8([[o]]); +true + +# bad arguments +gap> INV_MAT8BIT_MUTABLE(fail); +Error, INV_MAT8BIT_MUTABLE: must belong to Is8BitMatrixRep (not the valu\ +e 'fail') + +# +# INV_MAT8BIT_SAME_MUTABILITY +# +gap> INV_MAT8BIT_SAME_MUTABILITY(ZeroRowMat8()); +Error, INV_MAT8BIT_SAME_MUTABILITY: compressed 8bit matrices with empty rows a\ +re not supported +gap> INV_MAT8BIT_SAME_MUTABILITY(M8([[o]])) = M8([[o]]); +true + +# bad arguments +gap> INV_MAT8BIT_SAME_MUTABILITY(fail); +Error, INV_MAT8BIT_SAME_MUTABILITY: must belong to Is8BitMatrixRep (not \ +the value 'fail') + +# +# INV_MAT8BIT_IMMUTABLE +# +gap> INV_MAT8BIT_IMMUTABLE(ZeroRowMat8()); +Error, INV_MAT8BIT_IMMUTABLE: compressed 8bit matrices with empty rows are not\ + supported +gap> INV_MAT8BIT_IMMUTABLE(IM8([[o]])) = IM8([[o]]); +true + +# bad arguments +gap> INV_MAT8BIT_IMMUTABLE(fail); +Error, INV_MAT8BIT_IMMUTABLE: must belong to Is8BitMatrixRep (not the va\ +lue 'fail') + +# +# ASS_MAT8BIT +# +gap> ASS_MAT8BIT(ZeroRowMat8(), 1, empty); +Error, ASS_MAT8BIT: compressed 8bit matrices with empty rows are not supported +gap> m := Mx08(1);; ASS_MAT8BIT(m, 2, empty);; m = Mx08(2); +true + +# bad arguments +gap> ASS_MAT8BIT(fail, 1, empty); +Error, ASS_MAT8BIT: must belong to Is8BitMatrixRep (not the value 'fail'\ +) +gap> ASS_MAT8BIT(ZeroRowMat8(), fail, empty); +Error, ASS_MAT8BIT: compressed 8bit matrices with empty rows are not supported +gap> ASS_MAT8BIT(ZeroRowMat8(), 1, fail); +Error, ASS_MAT8BIT: compressed 8bit matrices with empty rows are not supported + +# +# ELM_MAT8BIT +# +gap> ELM_MAT8BIT(Mx08(2), 1); +< mutable compressed vector length 0 over GF(5) > + +# bad arguments +gap> ELM_MAT8BIT(fail, 1); +Error, ELM_MAT8BIT: must belong to Is8BitMatrixRep (not the value 'fail'\ +) +gap> ELM_MAT8BIT(Mx08(2), fail); +Error, ELM_MAT8BIT: must be a positive small integer (not the value 'fai\ +l') + +# +# SWAP_ROWS_MAT8BIT +# +gap> m := Mx08(2);; SWAP_ROWS_MAT8BIT(m, 1, 2);; m = Mx08(2); +true + +# bad arguments +gap> SWAP_ROWS_MAT8BIT(fail, 1, 2); +Error, SWAP_ROWS_MAT8BIT: must belong to Is8BitMatrixRep (not the value \ +'fail') +gap> SWAP_ROWS_MAT8BIT(m, fail, 2); +Error, SWAP_ROWS_MAT8BIT: must be a small integer (not the value 'fail'\ +) +gap> SWAP_ROWS_MAT8BIT(m, 1, fail); +Error, SWAP_ROWS_MAT8BIT: must be a small integer (not the value 'fail'\ +) + +# +# SWAP_COLS_MAT8BIT +# +gap> m := ZeroRowMat8();; SWAP_COLS_MAT8BIT(m, 1, 1);; EQ_MAT8BIT_MAT8BIT(m, ZeroRowMat8()); +true + +# bad arguments +gap> SWAP_COLS_MAT8BIT(fail, 1, 1); +Error, SWAP_COLS_MAT8BIT: must belong to Is8BitMatrixRep (not the value \ +'fail') +gap> SWAP_COLS_MAT8BIT(m, fail, 1); +Error, SWAP_COLS_MAT8BIT: must be a small integer (not the value 'fail'\ +) +gap> SWAP_COLS_MAT8BIT(m, 1, fail); +Error, SWAP_COLS_MAT8BIT: must be a small integer (not the value 'fail'\ +) + +# +# SUM_MAT8BIT_MAT8BIT +# +gap> SUM_MAT8BIT_MAT8BIT(ZeroRowMat8(), ZeroRowMat8()); +Error, SUM_MAT8BIT_MAT8BIT: compressed 8bit matrices with empty rows are not s\ +upported +gap> SUM_MAT8BIT_MAT8BIT(Mx08(2), Mx08(2)) = Mx08(2); +true + +# bad arguments +gap> SUM_MAT8BIT_MAT8BIT(fail, ZeroRowMat8()); +Error, SUM_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the value\ + 'fail') +gap> SUM_MAT8BIT_MAT8BIT(ZeroRowMat8(), fail); +Error, SUM_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the value\ + 'fail') + +# +# DIFF_MAT8BIT_MAT8BIT +# +gap> DIFF_MAT8BIT_MAT8BIT(ZeroRowMat8(), ZeroRowMat8()); +Error, DIFF_MAT8BIT_MAT8BIT: compressed 8bit matrices with empty rows are not \ +supported +gap> DIFF_MAT8BIT_MAT8BIT(Mx08(2), Mx08(2)) = Mx08(2); +true + +# bad arguments +gap> DIFF_MAT8BIT_MAT8BIT(fail, ZeroRowMat8()); +Error, DIFF_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the valu\ +e 'fail') +gap> DIFF_MAT8BIT_MAT8BIT(ZeroRowMat8(), fail); +Error, DIFF_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the valu\ +e 'fail') + +# +# ADD_COEFFS_VEC8BIT_3 +# +gap> v := V8([]);; ADD_COEFFS_VEC8BIT_3(v, empty, o); +0 +gap> v; +< mutable compressed vector length 0 over GF(5) > + +# bad arguments +gap> ADD_COEFFS_VEC8BIT_3(fail, empty, o); +Error, ADD_COEFFS_VEC8BIT_3: must belong to Is8BitVectorRep (not the va\ +lue 'fail') +gap> ADD_COEFFS_VEC8BIT_3(v, fail, o); +Error, ADD_COEFFS_VEC8BIT_3: must belong to Is8BitVectorRep (not the va\ +lue 'fail') +gap> ADD_COEFFS_VEC8BIT_3(v, empty, fail); +Error, ADD_COEFFS_VEC8BIT_3: must be a finite field element (not the va\ +lue 'fail') + +# +# ADD_COEFFS_VEC8BIT_2 +# +gap> v := V8([]);; ADD_COEFFS_VEC8BIT_2(v, empty); +0 +gap> v; +< mutable compressed vector length 0 over GF(5) > + +# bad arguments +gap> ADD_COEFFS_VEC8BIT_2(fail, empty); +Error, ADD_COEFFS_VEC8BIT_2: must belong to Is8BitVectorRep (not the va\ +lue 'fail') +gap> ADD_COEFFS_VEC8BIT_2(v, fail); +Error, ADD_COEFFS_VEC8BIT_2: must belong to Is8BitVectorRep (not the va\ +lue 'fail') + +# +# SHIFT_VEC8BIT_LEFT +# +gap> v := V8([]);; SHIFT_VEC8BIT_LEFT(v, 3);; v = empty; +true + +# bad arguments +gap> SHIFT_VEC8BIT_LEFT(fail, 3); +Error, SHIFT_VEC8BIT_LEFT: must belong to Is8BitVectorRep (not the value\ + 'fail') +gap> SHIFT_VEC8BIT_LEFT(v, fail); +Error, SHIFT_VEC8BIT_LEFT: must be a non-negative small integer (not \ +the value 'fail') + +# +# SHIFT_VEC8BIT_RIGHT +# +gap> v := V8([]);; SHIFT_VEC8BIT_RIGHT(v, 3, z);; v = V8([z, z, z]); +true + +# bad arguments +gap> SHIFT_VEC8BIT_RIGHT(fail, 3, z); +Error, SHIFT_VEC8BIT_RIGHT: must belong to Is8BitVectorRep (not the valu\ +e 'fail') +gap> SHIFT_VEC8BIT_RIGHT(v, fail, z); +Error, SHIFT_VEC8BIT_RIGHT: must be a non-negative small integer (not\ + the value 'fail') +gap> SHIFT_VEC8BIT_RIGHT(v, 3, fail); +Error, SHIFT_VEC8BIT_RIGHT: must be a finite field element (not the val\ +ue 'fail') + +# +# RESIZE_VEC8BIT +# +gap> v := V8([]);; RESIZE_VEC8BIT(v, 2);; v = V8([z, z]); +true + +# bad arguments +gap> RESIZE_VEC8BIT(fail, 2); +Error, RESIZE_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fa\ +il') +gap> RESIZE_VEC8BIT(v, fail); +Error, RESIZE_VEC8BIT: must be a non-negative small integer (not the\ + value 'fail') + +# +# RIGHTMOST_NONZERO_VEC8BIT +# +gap> RIGHTMOST_NONZERO_VEC8BIT(empty); +0 +gap> RIGHTMOST_NONZERO_VEC8BIT(V8([z, o])); +2 + +# bad arguments +gap> RIGHTMOST_NONZERO_VEC8BIT(fail); +Error, RIGHTMOST_NONZERO_VEC8BIT: must belong to Is8BitVectorRep (not th\ +e value 'fail') + +# +# PROD_COEFFS_VEC8BIT +# +gap> PROD_COEFFS_VEC8BIT(empty, 0, empty, 0); +< mutable compressed vector length 0 over GF(5) > +gap> PROD_COEFFS_VEC8BIT(one, 1, one, 1); +[ Z(5)^0 ] + +# bad arguments +gap> PROD_COEFFS_VEC8BIT(fail, 0, empty, 0); +Error, PROD_COEFFS_VEC8BIT: must belong to Is8BitVectorRep (not the value\ + 'fail') +gap> PROD_COEFFS_VEC8BIT(empty, fail, empty, 0); +Error, PROD_COEFFS_VEC8BIT: must be a non-negative small integer (not the\ + value 'fail') +gap> PROD_COEFFS_VEC8BIT(empty, 0, fail, 0); +Error, PROD_COEFFS_VEC8BIT: must belong to Is8BitVectorRep (not the value\ + 'fail') +gap> PROD_COEFFS_VEC8BIT(empty, 0, empty, fail); +Error, PROD_COEFFS_VEC8BIT: must be a non-negative small integer (not the\ + value 'fail') + +# +# REDUCE_COEFFS_VEC8BIT +# +gap> s := MAKE_SHIFTED_COEFFS_VEC8BIT(V8([o]), 1);; +gap> v := V8([o]);; REDUCE_COEFFS_VEC8BIT(v, 1, s); +0 +gap> v; +< mutable compressed vector length 0 over GF(5) > + +# bad arguments +gap> REDUCE_COEFFS_VEC8BIT(fail, 1, s); +Error, REDUCE_COEFFS_VEC8BIT: must belong to Is8BitVectorRep (not the val\ +ue 'fail') +gap> REDUCE_COEFFS_VEC8BIT(v, fail, s); +Error, REDUCE_COEFFS_VEC8BIT: must be a non-negative small integer (not t\ +he value 'fail') +gap> REDUCE_COEFFS_VEC8BIT(v, 1, fail); +Error, REDUCE_COEFFS_VEC8BIT: must be a plain list (not the value \ +'fail') + +# +# QUOTREM_COEFFS_VEC8BIT +# +gap> s := MAKE_SHIFTED_COEFFS_VEC8BIT(V8([o]), 1);; +gap> QUOTREM_COEFFS_VEC8BIT(empty, 0, s); +[ < mutable compressed vector length 0 over GF(5) >, + < mutable compressed vector length 0 over GF(5) > ] + +# bad arguments +gap> QUOTREM_COEFFS_VEC8BIT(fail, 0, s); +Error, QUOTREM_COEFFS_VEC8BIT: must belong to Is8BitVectorRep (not the va\ +lue 'fail') +gap> QUOTREM_COEFFS_VEC8BIT(empty, fail, s); +Error, QUOTREM_COEFFS_VEC8BIT: must be a non-negative small integer (not \ +the value 'fail') +gap> QUOTREM_COEFFS_VEC8BIT(empty, 0, fail); +Error, QUOTREM_COEFFS_VEC8BIT: must be a plain list (not the value\ + 'fail') + +# +# MAKE_SHIFTED_COEFFS_VEC8BIT +# +gap> s := MAKE_SHIFTED_COEFFS_VEC8BIT(V8([o]), 1);; s[4]; +1 +gap> s[5]; +Z(5)^0 + +# bad arguments +gap> MAKE_SHIFTED_COEFFS_VEC8BIT(fail, 1); +Error, MAKE_SHIFTED_COEFFS_VEC8BIT: must belong to Is8BitVectorRep (not t\ +he value 'fail') +gap> MAKE_SHIFTED_COEFFS_VEC8BIT(V8([o]), fail); +Error, MAKE_SHIFTED_COEFFS_VEC8BIT: must be a non-negative small integer \ +(not the value 'fail') + +# +# DISTANCE_DISTRIB_VEC8BITS +# +gap> d := [0, 0];; DISTANCE_DISTRIB_VEC8BITS(Veclis8([one]), oneZero, d);; d; +[ 1, 4 ] + +# bad arguments +gap> DISTANCE_DISTRIB_VEC8BITS(fail, oneZero, d); +Error, DISTANCE_DISTRIB_VEC8BITS: must be a plain list (not the value\ + 'fail') +gap> DISTANCE_DISTRIB_VEC8BITS(Veclis8([one]), fail, d); +Error, DISTANCE_DISTRIB_VEC8BITS: must belong to Is8BitVectorRep (not th\ +e value 'fail') +gap> DISTANCE_DISTRIB_VEC8BITS(Veclis8([one]), oneZero, fail); +Error, DISTANCE_DISTRIB_VEC8BITS: must be a plain list (not the value 'fai\ +l') + +# +# A_CLOSEST_VEC8BIT +# +gap> A_CLOSEST_VEC8BIT(Veclis8([one]), one, 0, 0); +[ Z(5)^0 ] + +# bad arguments +gap> A_CLOSEST_VEC8BIT(fail, one, 0, 0); +Error, A_CLOSEST_VEC8BIT: must be a plain list (not the value 'fail') +gap> A_CLOSEST_VEC8BIT(Veclis8([one]), fail, 0, 0); +Error, A_CLOSEST_VEC8BIT: must belong to Is8BitVectorRep (not the value \ +'fail') +gap> A_CLOSEST_VEC8BIT(Veclis8([one]), one, fail, 0); +Error, A_CLOSEST_VEC8BIT: must be a non-negative small integer (not the \ +value 'fail') +gap> A_CLOSEST_VEC8BIT(Veclis8([one]), one, 0, fail); +Error, A_CLOSEST_VEC8BIT: must be a non-negative small integer (not the\ + value 'fail') + +# +# A_CLOSEST_VEC8BIT_COORDS +# +gap> A_CLOSEST_VEC8BIT_COORDS(Veclis8([one]), one, 0, 0); +[ [ Z(5)^0 ], [ 1 ] ] + +# bad arguments +gap> A_CLOSEST_VEC8BIT_COORDS(fail, one, 0, 0); +Error, A_CLOSEST_VEC8BIT_COORDS: must be a plain list (not the value \ +'fail') +gap> A_CLOSEST_VEC8BIT_COORDS(Veclis8([one]), fail, 0, 0); +Error, A_CLOSEST_VEC8BIT_COORDS: must belong to Is8BitVectorRep (not the\ + value 'fail') +gap> A_CLOSEST_VEC8BIT_COORDS(Veclis8([one]), one, fail, 0); +Error, A_CLOSEST_VEC8BIT_COORDS: must be a non-negative small integer (n\ +ot the value 'fail') +gap> A_CLOSEST_VEC8BIT_COORDS(Veclis8([one]), one, 0, fail); +Error, A_CLOSEST_VEC8BIT_COORDS: must be a non-negative small integer (\ +not the value 'fail') + +# +# COSET_LEADERS_INNER_8BITS +# +gap> leaders := [Immutable(oneZero)];; leaders[6] := false;; + +#gap> COSET_LEADERS_INNER_8BITS(Veclis8([one]), 1, 1, leaders, f5); +#4 +#gap> leaders[2]; +#[ Z(5)^0 ] +# +# bad arguments +gap> COSET_LEADERS_INNER_8BITS(fail, 1, 1, leaders, f5); +Error, COSET_LEADERS_INNER_8BITS: must be a plain list (not the value\ + 'fail') +gap> COSET_LEADERS_INNER_8BITS(Veclis8([one]), fail, 1, leaders, f5); +Error, COSET_LEADERS_INNER_8BITS: must be a small integer (not the va\ +lue 'fail') +gap> COSET_LEADERS_INNER_8BITS(Veclis8([one]), 1, fail, leaders, f5); +Error, COSET_LEADERS_INNER_8BITS: must be a small integer (not the va\ +lue 'fail') +gap> COSET_LEADERS_INNER_8BITS(Veclis8([one]), 1, 1, fail, f5); +Error, COSET_LEADERS_INNER_8BITS: must be a plain list (not the valu\ +e 'fail') +gap> COSET_LEADERS_INNER_8BITS(Veclis8([one]), 1, 1, leaders, fail); +Error, COSET_LEADERS_INNER_8BITS: must be a plain list (not the value \ +'fail') + +# +# SEMIECHELON_LIST_VEC8BITS +# +gap> s := SEMIECHELON_LIST_VEC8BITS([one]);; s.heads = [1] and s.vectors = [one]; +true + +# bad arguments +gap> SEMIECHELON_LIST_VEC8BITS(fail); +Error, SEMIECHELON_LIST_VEC8BITS: must be a plain list (not the value 'f\ +ail') + +# +# SEMIECHELON_LIST_VEC8BITS_TRANSFORMATIONS +# +gap> s := SEMIECHELON_LIST_VEC8BITS_TRANSFORMATIONS([one]);; s.heads = [1] and s.vectors = [one] and s.coeffs = [one]; +true + +# bad arguments +gap> SEMIECHELON_LIST_VEC8BITS_TRANSFORMATIONS(fail); +Error, SEMIECHELON_LIST_VEC8BITS_TRANSFORMATIONS: must be a plain list (\ +not the value 'fail') + +# +# TRIANGULIZE_LIST_VEC8BITS +# +gap> m := [one];; TRIANGULIZE_LIST_VEC8BITS(m);; m = [one]; +true + +# bad arguments +gap> TRIANGULIZE_LIST_VEC8BITS(fail); +Error, TRIANGULIZE_LIST_VEC8BITS: must be a plain list (not the value 'f\ +ail') + +# +# RANK_LIST_VEC8BITS +# +gap> RANK_LIST_VEC8BITS([one]); +1 + +# bad arguments +gap> RANK_LIST_VEC8BITS(fail); +Error, RANK_LIST_VEC8BITS: must be a plain list (not the value 'fail') + +# +# DETERMINANT_LIST_VEC8BITS +# +gap> DETERMINANT_LIST_VEC8BITS([one]); +Z(5)^0 + +# bad arguments +gap> DETERMINANT_LIST_VEC8BITS(fail); +Error, DETERMINANT_LIST_VEC8BITS: must be a plain list (not the value 'f\ +ail') + +# +# EQ_MAT8BIT_MAT8BIT +# +gap> EQ_MAT8BIT_MAT8BIT(Mx08(2), Mx08(2)) and EQ_MAT8BIT_MAT8BIT(ZeroRowMat8(), ZeroRowMat8()); +true + +# bad arguments +gap> EQ_MAT8BIT_MAT8BIT(fail, Mx08(2)); +Error, EQ_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the value \ +'fail') +gap> EQ_MAT8BIT_MAT8BIT(Mx08(2), fail); +Error, EQ_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the value \ +'fail') + +# +# LT_MAT8BIT_MAT8BIT +# +gap> LT_MAT8BIT_MAT8BIT(ZeroRowMat8(), Mx08(1)) and not LT_MAT8BIT_MAT8BIT(Mx08(1), ZeroRowMat8()); +true + +# bad arguments +gap> LT_MAT8BIT_MAT8BIT(fail, Mx08(1)); +Error, LT_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the value \ +'fail') +gap> LT_MAT8BIT_MAT8BIT(ZeroRowMat8(), fail); +Error, LT_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the value \ +'fail') + +# +# TRANSPOSED_MAT8BIT +# +gap> TRANSPOSED_MAT8BIT(ZeroRowMat8()); +Error, TRANSPOSED_MAT8BIT: compressed 8bit matrices with empty rows are not su\ +pported +gap> EQ_MAT8BIT_MAT8BIT(TRANSPOSED_MAT8BIT(Mx08(2)), ZeroRowMat8()); +true + +# bad arguments gap> TRANSPOSED_MAT8BIT(fail); Error, TRANSPOSED_MAT8BIT: must belong to Is8BitMatrixRep (not the value\ 'fail') +# +# KRONECKERPRODUCT_MAT8BIT_MAT8BIT +# +gap> KRONECKERPRODUCT_MAT8BIT_MAT8BIT(ZeroRowMat8(), ZeroRowMat8()); +Error, KRONECKERPRODUCT_MAT8BIT_MAT8BIT: compressed 8bit matrices with empty r\ +ows are not supported +gap> KRONECKERPRODUCT_MAT8BIT_MAT8BIT(Mx08(2), M8([[o]])) = Mx08(2); +true + +# bad arguments +gap> KRONECKERPRODUCT_MAT8BIT_MAT8BIT(fail, ZeroRowMat8()); +Error, KRONECKERPRODUCT_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep\ + (not the value 'fail') +gap> KRONECKERPRODUCT_MAT8BIT_MAT8BIT(ZeroRowMat8(), fail); +Error, KRONECKERPRODUCT_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep\ + (not the value 'fail') + +# +# MAT_ELM_MAT8BIT +# +gap> MAT_ELM_MAT8BIT(M8([[o]]), 1, 1); +Z(5)^0 + +# bad arguments +gap> MAT_ELM_MAT8BIT(fail, 1, 1); +Error, MAT_ELM_MAT8BIT: must belong to Is8BitMatrixRep (not the value 'f\ +ail') +gap> MAT_ELM_MAT8BIT(M8([[o]]), fail, 1); +Error, MAT_ELM_MAT8BIT: must be a positive small integer (not the value \ +'fail') +gap> MAT_ELM_MAT8BIT(M8([[o]]), 1, fail); +Error, MAT_ELM_MAT8BIT: must be a positive small integer (not the value \ +'fail') + +# +# SET_MAT_ELM_MAT8BIT +# +gap> m := M8([[z]]);; SET_MAT_ELM_MAT8BIT(m, 1, 1, o);; m = M8([[o]]); +true + +# bad arguments +gap> SET_MAT_ELM_MAT8BIT(fail, 1, 1, o); +Error, SET_MAT_ELM_MAT8BIT: must belong to Is8BitMatrixRep (not the valu\ +e 'fail') +gap> SET_MAT_ELM_MAT8BIT(m, fail, 1, o); +Error, SET_MAT_ELM_MAT8BIT: must be a positive small integer (not the va\ +lue 'fail') +gap> SET_MAT_ELM_MAT8BIT(m, 1, fail, o); +Error, SET_MAT_ELM_MAT8BIT: must be a positive small integer (not the va\ +lue 'fail') +gap> SET_MAT_ELM_MAT8BIT(m, 1, 1, fail); +Error, Attempt to convert locked compressed vector to plain list + # gap> STOP_TEST("kernel/vec8bit.tst"); diff --git a/tst/testinstall/kernel/vecgf2.tst b/tst/testinstall/kernel/vecgf2.tst index 7c4a838349..c3021d52cb 100644 --- a/tst/testinstall/kernel/vecgf2.tst +++ b/tst/testinstall/kernel/vecgf2.tst @@ -2,10 +2,981 @@ # Tests for functions defined in src/vecgf2.c # gap> START_TEST("kernel/vecgf2.tst"); +gap> z := 0*Z(2);; +gap> o := Z(2)^0;; +gap> V2 := function(list) +> local v; +> v := ShallowCopy(list); +> CONV_GF2VEC(v); +> return v; +> end;; +gap> M2 := function(rows) +> local m, i; +> m := List(rows, ShallowCopy); +> for i in [1 .. Length(m)] do +> CONV_GF2VEC(m[i]); +> od; +> CONV_GF2MAT(m); +> return m; +> end;; +gap> Mx02 := n -> M2(List([1 .. n], i -> []));; +gap> Veclis2 := function(rows) +> local f, fdi, fdip, veclis, row, mults, j, mult; +> f := AsSSortedList(GF(2)); +> fdi := []; +> for j in [2 .. Length(f)] do +> fdi[j - 1] := f[j] - f[j - 1]; +> od; +> Add(fdi, -Last(f)); +> fdip := List(fdi, x -> Position(fdi, x)); +> veclis := []; +> for row in rows do +> mults := []; +> mults[Length(fdi) + 1] := false; +> for j in [1 .. Length(fdi)] do +> if fdip[j] < j then +> mult := mults[fdip[j]]; +> else +> mult := fdi[j] * row; +> fi; +> mults[j] := mult; +> od; +> Add(veclis, mults); +> od; +> return veclis; +> end;; +gap> empty := V2([]);; +gap> one := V2([o]);; +gap> oneZero := V2([z]);; # +# CONV_GF2VEC +# +gap> v := [];; CONV_GF2VEC(v); v; + + +# bad arguments +gap> CONV_GF2VEC(fail); +Error, CONV_GF2VEC: must be a small list (not the value 'fail') + +# +# COPY_GF2VEC +# +gap> v := COPY_GF2VEC([]); + + +# bad arguments +gap> COPY_GF2VEC(fail); +Error, COPY_GF2VEC: argument must be a list of GF2 elements + +# +# PLAIN_GF2VEC +# +gap> v := V2([]);; PLAIN_GF2VEC(v);; IsPlistRep(v) and Length(v) = 0; +true + +# bad arguments +gap> PLAIN_GF2VEC(fail); +Error, PLAIN_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# PLAIN_GF2MAT +# +gap> m := Mx02(2);; PLAIN_GF2MAT(m);; IsPlistRep(m) and m = [[], []]; +true + +# bad arguments +gap> PLAIN_GF2MAT(fail); +Error, PLAIN_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# EQ_GF2VEC_GF2VEC +# +gap> EQ_GF2VEC_GF2VEC(empty, empty); +true +gap> EQ_GF2VEC_GF2VEC(empty, one); +false + +# bad arguments +gap> EQ_GF2VEC_GF2VEC(fail, empty); +Error, EQ_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> EQ_GF2VEC_GF2VEC(empty, fail); +Error, EQ_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# LT_GF2VEC_GF2VEC +# +gap> LT_GF2VEC_GF2VEC(oneZero, one); +true +gap> LT_GF2VEC_GF2VEC(one, oneZero); +false + +# bad arguments +gap> LT_GF2VEC_GF2VEC(fail, one); +Error, LT_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> LT_GF2VEC_GF2VEC(oneZero, fail); +Error, LT_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# EQ_GF2MAT_GF2MAT +# +gap> EQ_GF2MAT_GF2MAT(Mx02(2), Mx02(2)); +true +gap> EQ_GF2MAT_GF2MAT(Mx02(1), Mx02(2)); +false + +# bad arguments +gap> EQ_GF2MAT_GF2MAT(fail, Mx02(2)); +Error, EQ_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> EQ_GF2MAT_GF2MAT(Mx02(2), fail); +Error, EQ_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# LT_GF2MAT_GF2MAT +# +gap> LT_GF2MAT_GF2MAT(Mx02(1), Mx02(2)); +true +gap> LT_GF2MAT_GF2MAT(Mx02(2), Mx02(1)); +false + +# bad arguments +gap> LT_GF2MAT_GF2MAT(fail, Mx02(2)); +Error, LT_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> LT_GF2MAT_GF2MAT(Mx02(1), fail); +Error, LT_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# LEN_GF2VEC +# +gap> LEN_GF2VEC(empty); +0 +gap> LEN_GF2VEC(V2([o, z])); +2 + +# bad arguments +gap> LEN_GF2VEC(fail); +Error, LEN_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# ELM0_GF2VEC +# +gap> ELM0_GF2VEC(empty, 1); +fail +gap> ELM0_GF2VEC(one, 1); +Z(2)^0 + +# bad arguments +gap> ELM0_GF2VEC(fail, 1); +Error, ELM0_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> ELM0_GF2VEC(empty, fail); +Error, ELM0_GF2VEC: must be a small integer (not the value 'fail') + +# +# ELM_GF2VEC +# +gap> ELM_GF2VEC(one, 1); +Z(2)^0 + +# bad arguments +gap> ELM_GF2VEC(fail, 1); +Error, ELM_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> ELM_GF2VEC(one, fail); +Error, ELM_GF2VEC: must be a small integer (not the value 'fail') + +# +# ELMS_GF2VEC +# +gap> ELMS_GF2VEC(empty, []) = empty; +true +gap> ELMS_GF2VEC(V2([o, z]), [1]); + + +# bad arguments +gap> ELMS_GF2VEC(fail, []); +Error, ELMS_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> ELMS_GF2VEC(empty, fail); +Error, Length: must be a list (not the value 'fail') + +# +# ASS_GF2VEC +# +gap> v := V2([]);; ASS_GF2VEC(v, 1, z);; v = oneZero; +true + +# bad arguments +gap> ASS_GF2VEC(fail, 1, z); +Error, ASS_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> ASS_GF2VEC(v, fail, z); +Error, ASS_GF2VEC: must be a small integer (not the value 'fail') +gap> ASS_GF2VEC(v, 1, fail); + +# +# ELM_GF2MAT +# +gap> ELM_GF2MAT(Mx02(2), 1); + + +# bad arguments +gap> ELM_GF2MAT(fail, 1); +Error, ELM_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> ELM_GF2MAT(Mx02(2), fail); +Error, ELM_GF2MAT: must be a small integer (not the value 'fail') + +# +# ASS_GF2MAT +# +gap> m := M2([[]]);; ASS_GF2MAT(m, 2, empty);; m = Mx02(2); +true + +# bad arguments +gap> ASS_GF2MAT(fail, 2, empty); +Error, ASS_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> ASS_GF2MAT(m, fail, empty); +Error, ASS_GF2MAT: must be a small integer (not the value 'fail') +gap> ASS_GF2MAT(m, 2, fail); + +# +# SWAP_ROWS_GF2MAT +# +gap> m := M2([[o], [z]]);; SWAP_ROWS_GF2MAT(m, 1, 2);; m = M2([[z], [o]]); +true + +# bad arguments +gap> SWAP_ROWS_GF2MAT(fail, 1, 2); +Error, SWAP_ROWS_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> SWAP_ROWS_GF2MAT(m, fail, 2); +Error, SWAP_ROWS_GF2MAT: must be a small integer (not the value 'fail') +gap> SWAP_ROWS_GF2MAT(m, 1, fail); +Error, SWAP_ROWS_GF2MAT: must be a small integer (not the value 'fail') + +# +# SWAP_COLS_GF2MAT +# +gap> m := M2([[o, z]]);; SWAP_COLS_GF2MAT(m, 1, 2);; m = M2([[z, o]]); +true + +# bad arguments +gap> SWAP_COLS_GF2MAT(fail, 1, 2); +Error, SWAP_COLS_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> SWAP_COLS_GF2MAT(m, fail, 2); +Error, SWAP_COLS_GF2MAT: must be a small integer (not the value 'fail') +gap> SWAP_COLS_GF2MAT(m, 1, fail); +Error, SWAP_COLS_GF2MAT: must be a small integer (not the value 'fail') + +# +# UNB_GF2VEC +# +gap> v := V2([o]);; UNB_GF2VEC(v, 1);; v = empty; +true + +# bad arguments +gap> UNB_GF2VEC(fail, 1); +Error, UNB_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> UNB_GF2VEC(v, fail); +Error, UNB_GF2VEC: must be a small integer (not the value 'fail') + +# +# UNB_GF2MAT +# +gap> m := M2([[]]);; UNB_GF2MAT(m, 1);; m = []; +true + +# bad arguments +gap> UNB_GF2MAT(fail, 1); +Error, UNB_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> UNB_GF2MAT(m, fail); +Error, UNB_GF2MAT: must be a small integer (not the value 'fail') + +# +# ZERO_GF2VEC +# +gap> ZERO_GF2VEC(empty); + +gap> ZERO_GF2VEC(V2([o, z])); + + +# bad arguments +gap> ZERO_GF2VEC(fail); +Error, ZERO_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# ZERO_GF2VEC_2 +# +gap> ZERO_GF2VEC_2(0); + +gap> ZERO_GF2VEC_2(2); + + +# bad arguments +gap> ZERO_GF2VEC_2(fail); +Error, ZERO_GF2VEC_2: must be a non-negative small integer (not the valu\ +e 'fail') + +# +# INV_GF2MAT_MUTABLE +# +gap> INV_GF2MAT_MUTABLE(M2([[o]])) = M2([[o]]); +true + +# bad arguments +gap> INV_GF2MAT_MUTABLE(fail); +Error, INV_GF2MAT_MUTABLE: must be a GF2 matrix (not the value 'fail') + +# +# INV_GF2MAT_SAME_MUTABILITY +# +gap> INV_GF2MAT_SAME_MUTABILITY(M2([[o]])) = M2([[o]]); +true + +# bad arguments +gap> INV_GF2MAT_SAME_MUTABILITY(fail); +Error, INV_GF2MAT_SAME_MUTABILITY: must be a GF2 matrix (not the value '\ +fail') + +# +# INV_GF2MAT_IMMUTABLE +# +gap> INV_GF2MAT_IMMUTABLE(Immutable(M2([[o]]))) = Immutable(M2([[o]])); +true + +# bad arguments +gap> INV_GF2MAT_IMMUTABLE(fail); +Error, INV_GF2MAT_IMMUTABLE: must be a GF2 matrix (not the value 'fail') + +# +# INV_PLIST_GF2VECS_DESTRUCTIVE +# +gap> m := [one];; INV_PLIST_GF2VECS_DESTRUCTIVE(m) = [one] and m = [one]; +true + +# bad arguments +gap> INV_PLIST_GF2VECS_DESTRUCTIVE(fail); +Error, INV_PLIST_GF2VECS_DESTRUCTIVE: must be a plain list (not the val\ +ue 'fail') + +# +# SUM_GF2VEC_GF2VEC +# +gap> SUM_GF2VEC_GF2VEC(empty, empty); + +gap> SUM_GF2VEC_GF2VEC(one, one); + + +# bad arguments +gap> SUM_GF2VEC_GF2VEC(fail, empty); +Error, SUM_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> SUM_GF2VEC_GF2VEC(empty, fail); +Error, SUM_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# PROD_GF2VEC_GF2VEC +# +gap> PROD_GF2VEC_GF2VEC(one, one); +Z(2)^0 + +# bad arguments +gap> PROD_GF2VEC_GF2VEC(fail, one); +Error, PROD_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> PROD_GF2VEC_GF2VEC(one, fail); +Error, PROD_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# PROD_GF2VEC_GF2MAT +# +gap> PROD_GF2VEC_GF2MAT(empty, Mx02(2)); + + +# bad arguments +gap> PROD_GF2VEC_GF2MAT(fail, Mx02(2)); +Error, PROD_GF2VEC_GF2MAT: must be a GF2 vector (not the value 'fail') +gap> PROD_GF2VEC_GF2MAT(empty, fail); +Error, PROD_GF2VEC_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# PROD_GF2MAT_GF2VEC +# +gap> PROD_GF2MAT_GF2VEC(Mx02(2), empty); + + +# bad arguments +gap> PROD_GF2MAT_GF2VEC(fail, empty); +Error, PROD_GF2MAT_GF2VEC: must be a GF2 matrix (not the value 'fail') +gap> PROD_GF2MAT_GF2VEC(Mx02(2), fail); +Error, PROD_GF2MAT_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# PROD_GF2MAT_GF2MAT +# +gap> PROD_GF2MAT_GF2MAT(M2([[o], [z]]), Mx02(1)) = Mx02(2); +true + +# bad arguments +gap> PROD_GF2MAT_GF2MAT(fail, Mx02(1)); +Error, PROD_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> PROD_GF2MAT_GF2MAT(M2([[o], [z]]), fail); +Error, PROD_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# PROD_GF2MAT_GF2MAT_SIMPLE +# +gap> PROD_GF2MAT_GF2MAT_SIMPLE(M2([[o], [z]]), Mx02(1)) = Mx02(2); +true + +# bad arguments +gap> PROD_GF2MAT_GF2MAT_SIMPLE(fail, Mx02(1)); +Error, PROD_GF2MAT_GF2MAT_SIMPLE: must be a GF2 matrix (not the value 'fa\ +il') +gap> PROD_GF2MAT_GF2MAT_SIMPLE(M2([[o], [z]]), fail); +Error, PROD_GF2MAT_GF2MAT_SIMPLE: must be a GF2 matrix (not the value 'fa\ +il') + +# +# PROD_GF2MAT_GF2MAT_ADVANCED +# +gap> PROD_GF2MAT_GF2MAT_ADVANCED(M2([[o]]), M2([[o]]), 1, 1) = M2([[o]]); +true + +# bad arguments +gap> PROD_GF2MAT_GF2MAT_ADVANCED(fail, M2([[o]]), 1, 1); +Error, PROD_GF2MAT_GF2MAT_ADVANCED: must be a GF2 matrix (not the value '\ +fail') +gap> PROD_GF2MAT_GF2MAT_ADVANCED(M2([[o]]), fail, 1, 1); +Error, PROD_GF2MAT_GF2MAT_ADVANCED: must be a GF2 matrix (not the value '\ +fail') +gap> PROD_GF2MAT_GF2MAT_ADVANCED(M2([[o]]), M2([[o]]), fail, 1); +Error, PROD_GF2MAT_GF2MAT_ADVANCED: must be a small integer (not\ + the value 'fail') +gap> PROD_GF2MAT_GF2MAT_ADVANCED(M2([[o]]), M2([[o]]), 1, fail); +Error, PROD_GF2MAT_GF2MAT_ADVANCED: must be a small integer (not t\ +he value 'fail') + +# +# ADDCOEFFS_GF2VEC_GF2VEC_MULT +# +gap> v := V2([]);; ADDCOEFFS_GF2VEC_GF2VEC_MULT(v, empty, z); +0 +gap> v; + + +# bad arguments +gap> ADDCOEFFS_GF2VEC_GF2VEC_MULT(fail, empty, z); +Error, ADDCOEFFS_GF2VEC_GF2VEC_MULT: must be a GF2 vector (not the value \ +'fail') +gap> ADDCOEFFS_GF2VEC_GF2VEC_MULT(v, fail, z); +Error, ADDCOEFFS_GF2VEC_GF2VEC_MULT: must be a GF2 vector (not the value \ +'fail') +gap> ADDCOEFFS_GF2VEC_GF2VEC_MULT(v, empty, fail); +Error, ADDCOEFFS_GF2VEC_GF2VEC_MULT: must be a finite field element (not\ + the value 'fail') + +# +# ADDCOEFFS_GF2VEC_GF2VEC +# +gap> v := V2([]);; ADDCOEFFS_GF2VEC_GF2VEC(v, empty); +0 +gap> v; + + +# bad arguments +gap> ADDCOEFFS_GF2VEC_GF2VEC(fail, empty); +Error, ADDCOEFFS_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail\ +') +gap> ADDCOEFFS_GF2VEC_GF2VEC(v, fail); +Error, ADDCOEFFS_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail\ +') + +# +# SHRINKCOEFFS_GF2VEC +# +gap> v := V2([o, z]);; SHRINKCOEFFS_GF2VEC(v); +1 +gap> v; + + +# bad arguments +gap> SHRINKCOEFFS_GF2VEC(fail); +Error, SHRINKCOEFFS_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# POSITION_NONZERO_GF2VEC +# +gap> POSITION_NONZERO_GF2VEC(empty, z); +1 +gap> POSITION_NONZERO_GF2VEC(one, z); +1 + +# bad arguments +gap> POSITION_NONZERO_GF2VEC(fail, z); +Error, POSITION_NONZERO_GF2VEC: must be a GF2 vector (not the value 'fai\ +l') +gap> POSITION_NONZERO_GF2VEC(empty, fail); +1 + +# +# POSITION_NONZERO_GF2VEC3 +# +gap> POSITION_NONZERO_GF2VEC3(empty, z, 1); +1 +gap> POSITION_NONZERO_GF2VEC3(V2([z, o]), z, 2); +3 + +# bad arguments +gap> POSITION_NONZERO_GF2VEC3(fail, z, 1); +Error, POSITION_NONZERO_GF2VEC3: must be a GF2 vector (not the value 'fa\ +il') +gap> POSITION_NONZERO_GF2VEC3(empty, fail, 1); +1 +gap> POSITION_NONZERO_GF2VEC3(empty, z, fail); +Error, POSITION_NONZERO_GF2VEC3: must be a non-negative small integer (\ +not the value 'fail') + +# +# MULT_VECTOR_GF2VECS_2 +# +gap> v := V2([o]);; MULT_VECTOR_GF2VECS_2(v, o);; v = one; +true + +# bad arguments +gap> MULT_VECTOR_GF2VECS_2(fail, o); +Error, MULT_VECTOR_GF2VECS_2: must be a GF2 vector (not the value 'fail') +gap> MULT_VECTOR_GF2VECS_2(v, fail); +Error, MULT_VECTOR_GF2VECS_2: must be a finite field element (not the va\ +lue 'fail') + +# +# APPEND_GF2VEC +# +gap> v := V2([]);; APPEND_GF2VEC(v, one);; v = one; +true + +# bad arguments +gap> APPEND_GF2VEC(fail, one); +Error, APPEND_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> APPEND_GF2VEC(v, fail); +Error, APPEND_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# SHALLOWCOPY_GF2VEC +# +gap> v := SHALLOWCOPY_GF2VEC(empty);; v = empty and not IsIdenticalObj(v, empty); +true + +# bad arguments +gap> SHALLOWCOPY_GF2VEC(fail); +Error, SHALLOWCOPY_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# NUMBER_GF2VEC +# +gap> NUMBER_GF2VEC(empty); +1 +gap> NUMBER_GF2VEC(one); +1 + +# bad arguments +gap> NUMBER_GF2VEC(fail); +Error, NUMBER_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# TRANSPOSED_GF2MAT +# +gap> TRANSPOSED_GF2MAT(Mx02(2)); +Error, row index 1 exceeds 0, the number of rows + +# bad arguments gap> TRANSPOSED_GF2MAT(fail); -Error, TRANSPOSED_GF2MAT: Need compressed matrix over GF(2) +Error, TRANSPOSED_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# DIST_GF2VEC_GF2VEC +# +gap> DIST_GF2VEC_GF2VEC(empty, empty); +0 +gap> DIST_GF2VEC_GF2VEC(one, one); +0 + +# bad arguments +gap> DIST_GF2VEC_GF2VEC(fail, empty); +Error, DIST_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> DIST_GF2VEC_GF2VEC(empty, fail); +Error, DIST_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# DIST_VEC_CLOS_VEC +# +gap> d := [0, 0];; DIST_VEC_CLOS_VEC(Veclis2([one]), oneZero, d);; d; +[ 1, 1 ] + +# bad arguments +gap> DIST_VEC_CLOS_VEC(fail, oneZero, d); +Error, DIST_VEC_CLOS_VEC: must be a plain list (not the value 'fail') +gap> DIST_VEC_CLOS_VEC(Veclis2([one]), fail, d); +Error, DIST_VEC_CLOS_VEC: must be a GF2 vector (not the value 'fail') +gap> DIST_VEC_CLOS_VEC(Veclis2([one]), oneZero, fail); +Error, DIST_VEC_CLOS_VEC: must be a plain list (not the value 'fail') + +# +# SUM_GF2MAT_GF2MAT +# +gap> SUM_GF2MAT_GF2MAT(Mx02(2), Mx02(2)) = Mx02(2); +true + +# bad arguments +gap> SUM_GF2MAT_GF2MAT(fail, Mx02(2)); +Error, SUM_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> SUM_GF2MAT_GF2MAT(Mx02(2), fail); +Error, SUM_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# A_CLOS_VEC +# +gap> A_CLOS_VEC(Veclis2([one]), one, 0, 0); + + +# bad arguments +gap> A_CLOS_VEC(fail, one, 0, 0); +Error, A_CLOS_VEC: must be a plain list (not the value 'fail') +gap> A_CLOS_VEC(Veclis2([one]), fail, 0, 0); +Error, A_CLOS_VEC: must be a GF2 vector (not the value 'fail') +gap> A_CLOS_VEC(Veclis2([one]), one, fail, 0); +Error, A_CLOS_VEC: must be a non-negative small integer (not the value '\ +fail') +gap> A_CLOS_VEC(Veclis2([one]), one, 0, fail); +Error, A_CLOS_VEC: must be a non-negative small integer (not the value \ +'fail') + +# +# A_CLOS_VEC_COORDS +# +gap> A_CLOS_VEC_COORDS(Veclis2([one]), one, 0, 0); +[ , [ 1 ] ] + +# bad arguments +gap> A_CLOS_VEC_COORDS(fail, one, 0, 0); +Error, A_CLOS_VEC_COORDS: must be a plain list (not the value 'fail') +gap> A_CLOS_VEC_COORDS(Veclis2([one]), fail, 0, 0); +Error, A_CLOS_VEC_COORDS: must be a GF2 vector (not the value 'fail') +gap> A_CLOS_VEC_COORDS(Veclis2([one]), one, fail, 0); +Error, A_CLOS_VEC_COORDS: must be a non-negative small integer (not the \ +value 'fail') +gap> A_CLOS_VEC_COORDS(Veclis2([one]), one, 0, fail); +Error, A_CLOS_VEC_COORDS: must be a non-negative small integer (not the\ + value 'fail') + +# +# COSET_LEADERS_INNER_GF2 +# +gap> leaders := [Immutable(oneZero)];; leaders[3] := false;; +gap> COSET_LEADERS_INNER_GF2(Veclis2([one]), 1, 1, leaders); +1 +gap> leaders[2]; + + +# bad arguments +gap> COSET_LEADERS_INNER_GF2(fail, 1, 1, leaders); +Error, COSET_LEADERS_INNER_GF2: must be a plain list (not the value '\ +fail') +gap> COSET_LEADERS_INNER_GF2(Veclis2([one]), fail, 1, leaders); +Error, COSET_LEADERS_INNER_GF2: must be a small integer (not the valu\ +e 'fail') +gap> COSET_LEADERS_INNER_GF2(Veclis2([one]), 1, fail, leaders); +Error, COSET_LEADERS_INNER_GF2: must be a small integer (not the valu\ +e 'fail') +gap> COSET_LEADERS_INNER_GF2(Veclis2([one]), 1, 1, fail); +Error, COSET_LEADERS_INNER_GF2: must be a plain list (not the value \ +'fail') + +# +# CONV_GF2MAT +# +gap> m := [V2([]), V2([])];; CONV_GF2MAT(m);; m = Mx02(2); +true + +# bad arguments +gap> CONV_GF2MAT(fail); +Error, CONV_GF2MAT: must be a small list (not the value 'fail') + +# +# PROD_GF2VEC_ANYMAT +# +gap> PROD_GF2VEC_ANYMAT(one, [fail]); +"TRY_NEXT_METHOD" +gap> PROD_GF2VEC_ANYMAT(one, [one]); + + +# bad arguments +gap> PROD_GF2VEC_ANYMAT(fail, [fail]); +Error, PROD_GF2VEC_ANYMAT: must be a GF2 vector (not the value 'fail') +gap> PROD_GF2VEC_ANYMAT(one, fail); +Error, PROD_GF2VEC_ANYMAT: must be a plain list (not the value 'fail') + +# +# RIGHTMOST_NONZERO_GF2VEC +# +gap> RIGHTMOST_NONZERO_GF2VEC(empty); +0 +gap> RIGHTMOST_NONZERO_GF2VEC(V2([z, o])); +2 + +# bad arguments +gap> RIGHTMOST_NONZERO_GF2VEC(fail); +Error, RIGHTMOST_NONZERO_GF2VEC: must be a GF2 vector (not the value 'fa\ +il') + +# +# RESIZE_GF2VEC +# +gap> v := V2([]);; RESIZE_GF2VEC(v, 2);; v = V2([z, z]); +true + +# bad arguments +gap> RESIZE_GF2VEC(fail, 2); +Error, RESIZE_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> RESIZE_GF2VEC(v, fail); +Error, RESIZE_GF2VEC: must be a non-negative small integer (not the v\ +alue 'fail') + +# +# SHIFT_LEFT_GF2VEC +# +gap> v := V2([]);; SHIFT_LEFT_GF2VEC(v, 3);; v = empty; +true + +# bad arguments +gap> SHIFT_LEFT_GF2VEC(fail, 3); +Error, SHIFT_LEFT_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> SHIFT_LEFT_GF2VEC(v, fail); +Error, SHIFT_LEFT_GF2VEC: must be a non-negative small integer (not t\ +he value 'fail') + +# +# SHIFT_RIGHT_GF2VEC +# +gap> v := V2([]);; SHIFT_RIGHT_GF2VEC(v, 3, z);; v = V2([z, z, z]); +true + +# bad arguments +gap> SHIFT_RIGHT_GF2VEC(fail, 3, z); +Error, SHIFT_RIGHT_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> SHIFT_RIGHT_GF2VEC(v, fail, z); +Error, SHIFT_RIGHT_GF2VEC: must be a non-negative small integer (not \ +the value 'fail') +gap> SHIFT_RIGHT_GF2VEC(v, 3, fail); +Error, SHIFT_RIGHT_GF2VEC: must be a finite field element (not the valu\ +e 'fail') + +# +# ADD_GF2VEC_GF2VEC_SHIFTED +# +gap> v := V2([]);; ADD_GF2VEC_GF2VEC_SHIFTED(v, one, 0, 1);; v = oneZero; +true + +# bad arguments +gap> ADD_GF2VEC_GF2VEC_SHIFTED(fail, one, 0, 1); +Error, ADD_GF2VEC_GF2VEC_SHIFTED: must be a GF2 vector (not the value '\ +fail') +gap> ADD_GF2VEC_GF2VEC_SHIFTED(v, fail, 0, 1); +Error, ADD_GF2VEC_GF2VEC_SHIFTED: must be a GF2 vector (not the value '\ +fail') +gap> ADD_GF2VEC_GF2VEC_SHIFTED(v, one, fail, 1); +Error, ADD_GF2VEC_GF2VEC_SHIFTED: must be a non-negative small integer \ +(not the value 'fail') +gap> ADD_GF2VEC_GF2VEC_SHIFTED(v, one, 0, fail); +Error, ADD_GF2VEC_GF2VEC_SHIFTED: must be a non-negative small integer (\ +not the value 'fail') + +# +# PROD_COEFFS_GF2VEC +# +gap> PROD_COEFFS_GF2VEC(empty, 0, empty, 0); + +gap> PROD_COEFFS_GF2VEC(one, 1, one, 1); + + +# bad arguments +gap> PROD_COEFFS_GF2VEC(fail, 0, empty, 0); + +gap> PROD_COEFFS_GF2VEC(empty, fail, empty, 0); +Error, PROD_COEFFS_GF2VEC: must be a non-negative small integer (not th\ +e value 'fail') +gap> PROD_COEFFS_GF2VEC(empty, 0, fail, 0); + +gap> PROD_COEFFS_GF2VEC(empty, 0, empty, fail); +Error, PROD_COEFFS_GF2VEC: must be a non-negative small integer (not th\ +e value 'fail') + +# +# REDUCE_COEFFS_GF2VEC +# +gap> v := V2([o]);; w := V2([o, z]);; +gap> REDUCE_COEFFS_GF2VEC(v, 1, w, 1); +0 +gap> v; + + +# bad arguments +gap> REDUCE_COEFFS_GF2VEC(fail, 1, w, 1); +Error, REDUCE_COEFFS_GF2VEC: must be a GF2 vector (not the value 'fail'\ +) +gap> REDUCE_COEFFS_GF2VEC(v, fail, w, 1); +Error, REDUCE_COEFFS_GF2VEC: must be a non-negative small integer (not \ +the value 'fail') +gap> REDUCE_COEFFS_GF2VEC(v, 1, fail, 1); +Error, REDUCE_COEFFS_GF2VEC: must be a GF2 vector (not the value 'fail'\ +) +gap> REDUCE_COEFFS_GF2VEC(v, 1, w, fail); +Error, REDUCE_COEFFS_GF2VEC: must be a non-negative small integer (not \ +the value 'fail') + +# +# QUOTREM_COEFFS_GF2VEC +# +gap> QUOTREM_COEFFS_GF2VEC(empty, 0, w, 1); +[ , ] + +# bad arguments +gap> QUOTREM_COEFFS_GF2VEC(fail, 0, w, 1); +Error, QUOTREM_COEFFS_GF2VEC: must be a GF2 vector (not the value 'fail\ +') +gap> QUOTREM_COEFFS_GF2VEC(empty, fail, w, 1); +Error, QUOTREM_COEFFS_GF2VEC: must be a non-negative small integer (not\ + the value 'fail') +gap> QUOTREM_COEFFS_GF2VEC(empty, 0, fail, 1); +Error, QUOTREM_COEFFS_GF2VEC: must be a GF2 vector (not the value 'fail\ +') +gap> QUOTREM_COEFFS_GF2VEC(empty, 0, w, fail); +Error, QUOTREM_COEFFS_GF2VEC: must be a non-negative small integer (not\ + the value 'fail') + +# +# SEMIECHELON_LIST_GF2VECS +# +gap> s := SEMIECHELON_LIST_GF2VECS([one]);; s.heads = [1] and s.vectors = [one]; +true + +# bad arguments +gap> SEMIECHELON_LIST_GF2VECS(fail); +Error, SEMIECHELON_LIST_GF2VECS: must be a plain list (not the value 'fa\ +il') + +# +# SEMIECHELON_LIST_GF2VECS_TRANSFORMATIONS +# +gap> s := SEMIECHELON_LIST_GF2VECS_TRANSFORMATIONS([one]);; +gap> s.heads; +[ 1 ] +gap> s.vectors = [one]; +true +gap> s.coeffs = [one]; +true + +# bad arguments +gap> SEMIECHELON_LIST_GF2VECS_TRANSFORMATIONS(fail); +Error, SEMIECHELON_LIST_GF2VECS_TRANSFORMATIONS: must be a plain list (n\ +ot the value 'fail') + +# +# TRIANGULIZE_LIST_GF2VECS +# +gap> m := [one];; TRIANGULIZE_LIST_GF2VECS(m);; m = [one]; +true + +# bad arguments +gap> TRIANGULIZE_LIST_GF2VECS(fail); +Error, TRIANGULIZE_LIST_GF2VECS: must be a plain list (not the value 'fa\ +il') + +# +# DETERMINANT_LIST_GF2VECS +# +gap> DETERMINANT_LIST_GF2VECS([one]); +Z(2)^0 + +# bad arguments +gap> DETERMINANT_LIST_GF2VECS(fail); +Error, DETERMINANT_LIST_GF2VECS: must be a plain list (not the value 'fa\ +il') + +# +# RANK_LIST_GF2VECS +# +gap> RANK_LIST_GF2VECS([one]); +1 + +# bad arguments +gap> RANK_LIST_GF2VECS(fail); +Error, RANK_LIST_GF2VECS: must be a plain list (not the value 'fail') + +# +# KRONECKERPRODUCT_GF2MAT_GF2MAT +# +gap> KRONECKERPRODUCT_GF2MAT_GF2MAT(Mx02(2), M2([[o]])) = Mx02(2); +true + +# bad arguments +gap> KRONECKERPRODUCT_GF2MAT_GF2MAT(fail, M2([[o]])); +Error, KRONECKERPRODUCT_GF2MAT_GF2MAT: must be a GF2 matrix (not the va\ +lue 'fail') +gap> KRONECKERPRODUCT_GF2MAT_GF2MAT(Mx02(2), fail); +Error, KRONECKERPRODUCT_GF2MAT_GF2MAT: must be a GF2 matrix (not the va\ +lue 'fail') + +# +# COPY_SECTION_GF2VECS +# +gap> src := V2([o, o]);; dst := V2([z, z, z]);; COPY_SECTION_GF2VECS(src, dst, 1, 2, 2);; dst = V2([z, o, o]); +true + +# bad arguments +gap> COPY_SECTION_GF2VECS(fail, dst, 1, 2, 2); +Error, COPY_SECTION_GF2VECS: must be a GF2 vector (not the value 'fail') +gap> COPY_SECTION_GF2VECS(src, fail, 1, 2, 2); +Error, COPY_SECTION_GF2VECS: must be a GF2 vector (not the value 'fail'\ +) +gap> COPY_SECTION_GF2VECS(src, dst, fail, 2, 2); +Error, COPY_SECTION_GF2VECS: must be a positive small integer (not the \ +value 'fail') +gap> COPY_SECTION_GF2VECS(src, dst, 1, fail, 2); +Error, COPY_SECTION_GF2VECS: must be a positive small integer (not the va\ +lue 'fail') +gap> COPY_SECTION_GF2VECS(src, dst, 1, 2, fail); +Error, COPY_SECTION_GF2VECS: must be a small integer (not the value \ +'fail') + +# +# MAT_ELM_GF2MAT +# +gap> MAT_ELM_GF2MAT(M2([[o]]), 1, 1); +Z(2)^0 + +# bad arguments +gap> MAT_ELM_GF2MAT(fail, 1, 1); +Error, MAT_ELM_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> MAT_ELM_GF2MAT(M2([[o]]), fail, 1); +Error, MAT_ELM_GF2MAT: must be a positive small integer (not the value '\ +fail') +gap> MAT_ELM_GF2MAT(M2([[o]]), 1, fail); +Error, MAT_ELM_GF2MAT: must be a positive small integer (not the value '\ +fail') + +# +# SET_MAT_ELM_GF2MAT +# +gap> m := M2([[z]]);; SET_MAT_ELM_GF2MAT(m, 1, 1, o);; m = M2([[o]]); +true + +# bad arguments +gap> SET_MAT_ELM_GF2MAT(fail, 1, 1, o); +Error, SET_MAT_ELM_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> SET_MAT_ELM_GF2MAT(m, fail, 1, o); +Error, SET_MAT_ELM_GF2MAT: must be a positive small integer (not the val\ +ue 'fail') +gap> SET_MAT_ELM_GF2MAT(m, 1, fail, o); +Error, SET_MAT_ELM_GF2MAT: must be a positive small integer (not the val\ +ue 'fail') +gap> SET_MAT_ELM_GF2MAT(m, 1, 1, fail); +Error, SET_MAT_ELM_GF2MAT: assigned element must be a GF(2) element (not the v\ +alue 'fail') # gap> STOP_TEST("kernel/vecgf2.tst"); From fb67a5c24f91ca31d1bae6cee2812de93c40cb17 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 22 May 2026 09:49:46 +0200 Subject: [PATCH 010/114] Document SemiSimpleType field restriction (#6408) Resolves #2570 Co-authored-by: Codex --- lib/alglie.gd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/alglie.gd b/lib/alglie.gd index 31cc718ee0..7200f28451 100644 --- a/lib/alglie.gd +++ b/lib/alglie.gd @@ -514,6 +514,11 @@ DeclareAttribute( "LieSolvableRadical", IsAlgebra and IsLieAlgebra ); ## Lie algebras. ## Then returns the type of L, i.e., ## a string containing the types of the simple summands of L. +## The field of L must not have characteristic 2 or 3, and the +## Killing form of L must be nondegenerate. +## If L has characteristic 0, the structure constants of L +## must be rational numbers; Lie algebras over arbitrary characteristic +## 0 fields are not supported. ## L:= SimpleLieAlgebra( "E", 8, Rationals );; ## gap> b:= BasisVectors( Basis( L ) );; From 36f7f08a97a81feb16b799a7e2fe6c750591d49a Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 22 May 2026 09:51:03 +0200 Subject: [PATCH 011/114] Clarify IsomorphismPcGroup docs (#6405) If input group is infinite or not solvable, fail is returned. --- lib/grp.gd | 8 ++++---- lib/grpfp.gi | 2 +- lib/pcgs.gd | 2 +- lib/pcgsspec.gi | 3 +++ tst/testinstall/grppc.tst | 25 +++++++++++++++++++++++++ 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/lib/grp.gd b/lib/grp.gd index f9127d72c0..2a83f80eba 100644 --- a/lib/grp.gd +++ b/lib/grp.gd @@ -4250,8 +4250,8 @@ DeclareGlobalFunction( "AllSmallNonabelianSimpleGroups" ); ## returns an isomorphism from G onto an isomorphic pc group. ## The series chosen for this pc representation depends on ## the method chosen. -## G must be a polycyclic group of any kind, for example a solvable -## permutation group. +## G must be a finite polycyclic group of any kind, for example a solvable +## permutation group. If G is finite but not solvable, fail is returned. ## G := Group( (1,2,3), (3,4,1) );; ## gap> iso := IsomorphismPcGroup( G ); @@ -4278,8 +4278,8 @@ DeclareAttribute( "IsomorphismPcGroup", IsGroup ); ## returns an isomorphism from G onto an isomorphic pc group ## whose family pcgs is a special pcgs. ## (This can be beneficial to the runtime of calculations.) -## G may be a polycyclic group of any kind, for example a solvable -## permutation group. +## G must be a finite polycyclic group of any kind, for example a solvable +## permutation group. If G is finite but not solvable, fail is returned. ## ## ## <#/GAPDoc> diff --git a/lib/grpfp.gi b/lib/grpfp.gi index 0546a1f18a..3eaee5e44e 100644 --- a/lib/grpfp.gi +++ b/lib/grpfp.gi @@ -4332,7 +4332,7 @@ local s, a, hom; fi; hom:=EpimorphismSolvableQuotient(G,s); if Size(Image(hom))<>s then - Error("group is not solvable"); + return fail; else SetIsInjective(hom, true); fi; diff --git a/lib/pcgs.gd b/lib/pcgs.gd index cf2c0a8338..e1cf7172d8 100644 --- a/lib/pcgs.gd +++ b/lib/pcgs.gd @@ -782,7 +782,7 @@ DeclareAttribute( "RefinedPcGroup", IsPcGroup ); ## ## ## isomorphic -## returns an isomorphism from G onto an isomorphic pc group +## returns an isomorphism from a pc group G onto an isomorphic pc group ## whose family pcgs is a prime order pcgs. ## ## diff --git a/lib/pcgsspec.gi b/lib/pcgsspec.gi index e8ff00d776..01cc3fdc62 100644 --- a/lib/pcgsspec.gi +++ b/lib/pcgsspec.gi @@ -752,6 +752,9 @@ InstallMethod( IsomorphismSpecialPcGroup, "generic method for groups", function(G) local iso; iso:=IsomorphismPcGroup(G); + if iso = fail then + return fail; + fi; return iso*IsomorphismSpecialPcGroup(Range(iso)); end); diff --git a/tst/testinstall/grppc.tst b/tst/testinstall/grppc.tst index 873257c589..b2501dfc65 100644 --- a/tst/testinstall/grppc.tst +++ b/tst/testinstall/grppc.tst @@ -1,17 +1,25 @@ #@local F,G,S,c,cl,f,g,g1,g10,g3,gens,h,hh,i,m,n,pcgs,r,rws,sys,u,v,x,y,iso gap> START_TEST("grppc.tst"); + +# gap> Display(TrivialGroup(IsPcGroup)); trivial pc-group + +# gap> Display(CyclicGroup(IsPcGroup, 10)); pc-group with 2 pc-generators and relations: g1^2 = g2 g2^5 = id all generators commute, the groups is abelian + +# gap> Display(SymmetricGroup(IsPcGroup, 3)); pc-group with 2 pc-generators and relations: g1^2 = id g2^3 = id g2^g1 = g2^2 + +# gap> h:=Group((1,2,3,4),(1,2));; gap> m:=IsomorphismPcGroup(h);; gap> hh:=Image(m,h);; @@ -30,6 +38,8 @@ all other pairs of generators commute gap> pcgs:=Pcgs(hh);; gap> ForAll(pcgs,i->PreImagesRepresentative(m,i) in h); true + +# gap> g:=WreathProduct(Group((1,2,3),(1,2)),Group((1,2,3,4,5,6,7)));; gap> i:=IsomorphismPcGroup(g);; gap> g:=Range(i);; @@ -183,6 +193,21 @@ true gap> IsIdenticalObj( Range( iso ), ImagesSource( iso ) ); true +# +gap> G:=AlternatingGroup(5);; +gap> IsomorphismPcGroup(G); +fail +gap> IsomorphismSpecialPcGroup(G); +fail +gap> G:=Range(IsomorphismFpGroup(G));; +gap> IsomorphismPcGroup(G); +fail +gap> IsomorphismSpecialPcGroup(G); +fail +gap> IsomorphismPcGroup(FreeGroup(1)); +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 3rd choice method found for `IsomorphismPcGroup' on 1 arguments + # gap> G:= AbelianGroup( IsPcGroup, [ 3, 3, 3 ] );; gap> S:= AbelianGroup( IsPcGroup, [ 3, 3 ] );; From 7d9c9f044cdc1b54b19e1f3e6cd527d0fed7fa5a Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 22 May 2026 09:54:23 +0200 Subject: [PATCH 012/114] Reformat and refactor StructureDescription code (#6403) Mostly avoid putting to many things on one line, for better readability and more accurate code coverage tracking. Also remove obsolete restrictions for perfect group orders 86016, 368640, 737280 --- lib/grpnames.gi | 229 ++++++++++++++++++++++++++---------------------- 1 file changed, 125 insertions(+), 104 deletions(-) diff --git a/lib/grpnames.gi b/lib/grpnames.gi index 11dcafd25e..695923570d 100644 --- a/lib/grpnames.gi +++ b/lib/grpnames.gi @@ -893,9 +893,11 @@ InstallMethod( DecompositionTypesOfGroup, # abelian special case if IsAbelian(G) then AG := AbelianInvariants(G); - if Length(AG) = 1 then DTypes := Set([AG[1]]); else + if Length(AG) = 1 then + DTypes := Set([AG[1]]); + else T := ["x"]; - for a in AG do Add(T,a); od; + Append(T, AG); DTypes := Set([T]); fi; return DTypes; @@ -942,7 +944,9 @@ InstallMethod( DecompositionTypesOfGroup, od; # default: a non-split extension - if Length(DTypes) = 0 then DTypes := Set([["non-split",Size(G)]]); fi; + if Length(DTypes) = 0 then + DTypes := Set([["non-split",Size(G)]]); + fi; return DTypes; end ); @@ -999,9 +1003,8 @@ function(G) gens := DoComputeDihedralGenerators(G); if gens = fail then return false; - else - SetDihedralGenerators(G, gens); fi; + SetDihedralGenerators(G, gens); return true; end); @@ -1198,27 +1201,31 @@ InstallMethod( IsAlternatingGroup, function ( G ) - local n, ids, info; + local info; if not IsFinite(G) then TryNextMethod(); fi; - if IsNaturalAlternatingGroup(G) then return true;fi; - if Size(G) < 60 then + if IsNaturalAlternatingGroup(G) then + return true; + elif Size(G) < 60 then if Size(G) = 1 then - SetAlternatingDegree(G,0); return true; + SetAlternatingDegree(G,0); + return true; elif Size(G) = 3 then - SetAlternatingDegree(G,3); return true; + SetAlternatingDegree(G,3); + return true; elif Size(G) = 12 and Size(DerivedSubgroup(G)) = 4 then - SetAlternatingDegree(G,4); return true; - else return false; fi; + SetAlternatingDegree(G,4); + return true; + fi; + elif IsSimpleGroup(G) then + info := IsomorphismTypeInfoFiniteSimpleGroup(G); + if info.series = "A" then + SetAlternatingDegree(G,info.parameter); + return true; + fi; fi; - - if not IsSimpleGroup(G) then return false; fi; - - info := IsomorphismTypeInfoFiniteSimpleGroup(G); - if info.series = "A" - then SetAlternatingDegree(G,info.parameter); return true; - else return false; fi; + return false; end ); ############################################################################# @@ -1272,7 +1279,9 @@ InstallMethod( IsSymmetricGroup, if not IsFinite(G) then TryNextMethod(); fi; # special treatment of small cases - if Size(G)<=2 then SetSymmetricDegree(G,Size(G)); return true; + if Size(G)<=2 then + SetSymmetricDegree(G,Size(G)); + return true; elif Size(G)=6 and not IsAbelian(G) then SetSymmetricDegree(G,3); return true; @@ -1407,15 +1416,15 @@ InstallGlobalFunction( LinearGroupParameters, if not IsPosInt(N) then Error(" must be positive integer"); fi; - # Formeln: + # Formulas: # |GL(n, q)| = Product(q^n - q^k : k in [0..n-1]) # |SL(n, q)| = |GL(n, q)| / (q - 1) # |PSL(n, q)| = |SL(n, q)| / gcd(n, q - 1) - # mit q = p^e f"ur p prim, e >= 1, n >= 1. + # where q = p^e for p prime, e >= 1, n >= 1. - # Betrachte N = |GL(n,q)|. Dann gilt f"ur n >= 2 - # (1) nu_p(N) = e * Binomial(n,2) und - # (2) (q - 1)^n teilt N. + # Consider N = |GL(n,q)|. Then we have for n >= 2 + # (1) nu_p(N) = e * Binomial(n,2) and + # (2) (q - 1)^n divides N. npeGL := [ ]; npeSL := [ ]; npePSL := [ ]; if N = 1 then return rec( npeGL := npeGL, npeSL := npeSL, npePSL := npePSL ); @@ -1470,8 +1479,9 @@ InstallMethod( IsPSL, # more than one npe-triple should only # occur in the cases |G| in [60, 168, 20160] - if Length(npes) > 1 and not( Size(G) in [60, 168, 20160] ) - then Error("algebraic panic! probably npe does not work"); fi; + if Length(npes) > 1 and not( Size(G) in [60, 168, 20160] ) then + Error("algebraic panic! probably npe does not work"); + fi; # set the parameters npe := npes[1]; @@ -1483,12 +1493,10 @@ InstallMethod( IsPSL, # PSL(2, 2) if npes[1] = [2, 2, 1] then if IsAbelian(G) then return false; fi; - SetParametersOfGroupViewedAsPSL(G,npe); return true; # PSL(2, 3) elif npes[1] = [2, 3, 1] then if Size(DerivedSubgroup(G)) <> 4 then return false; fi; - SetParametersOfGroupViewedAsPSL(G,npe); return true; # PSL(3, 4) / PSL(4, 2) \cong A_8 elif npes = [ [ 4, 2, 1 ], [ 3, 2, 2 ] ] then @@ -1497,13 +1505,13 @@ InstallMethod( IsPSL, else npe := npes[2]; fi; - SetParametersOfGroupViewedAsPSL(G,npe); return true; # other cases - else - if not IsSimpleGroup(G) then return false; fi; - SetParametersOfGroupViewedAsPSL(G,npe); return true; + elif not IsSimpleGroup(G) then + return false; fi; + SetParametersOfGroupViewedAsPSL(G,npe); + return true; end ); ############################################################################# @@ -1563,12 +1571,10 @@ InstallMethod( IsSL, # SL(2, 2) if npes = [2, 2, 1] then if IsAbelian(G) then return false; fi; - SetParametersOfGroupViewedAsSL(G,npes); return true; # SL(2, 3) elif npes = [2, 3, 1] then if Size(DerivedSubgroup(G)) <> 8 then return false; fi; - SetParametersOfGroupViewedAsSL(G,npes); return true; # other cases, in which the contained PSL is simple else @@ -1583,8 +1589,9 @@ InstallMethod( IsSL, then return false; fi; if IsomorphismGroups(G,SL(npes[1],npes[2]^npes[3])) = fail then return false; fi; - SetParametersOfGroupViewedAsSL(G,npes); return true; fi; + SetParametersOfGroupViewedAsSL(G,npes); + return true; end ); ############################################################################# @@ -1649,7 +1656,6 @@ InstallMethod( IsGL, # GL(2, 2) if npes = [2, 2, 1] then if IsAbelian(G) then return false; fi; - SetParametersOfGroupViewedAsGL(G,npes); return true; # GL(2, 3) elif npes = [2, 3, 1] then @@ -1668,7 +1674,6 @@ InstallMethod( IsGL, # elements of order 4 in one case, and 2 in the other; this is also # how e.g. IdGroup distinguishes them if Number(G, g -> Order(g) = 2) < 13 then return false; fi; - SetParametersOfGroupViewedAsGL(G,npes); return true; # other cases, in which contained PSL is simple else @@ -1687,8 +1692,9 @@ InstallMethod( IsGL, then return false; fi; if IsomorphismGroups(G,GL(npes[1],npes[2]^npes[3])) = fail then return false; fi; - SetParametersOfGroupViewedAsGL(G,npes); return true; fi; + SetParametersOfGroupViewedAsGL(G,npes); + return true; end ); ############################################################################# @@ -1728,23 +1734,21 @@ InstallMethod( GLUnderlyingField, BindGlobal( "SD_insertsep", # function to join parts of name function ( strs, sep, brack ) - local short, s, i; - - short := ValueOption("short") = true; + local s, i; if strs = [] then return ""; fi; strs := Filtered(strs,str->str<>""); if Length(strs) > 1 then for i in [1..Length(strs)] do - if Intersection(strs[i],brack) <> "" - then strs[i] := Concatenation("(",strs[i],")"); fi; + if Intersection(strs[i],brack) <> "" then + strs[i] := Concatenation("(",strs[i],")"); + fi; od; fi; - s := strs[1]; - for i in [2..Length(strs)] do - s := Concatenation(s,sep,strs[i]); - od; - if short then RemoveCharacters(s," "); fi; + s := JoinStringsWithSeparator(strs,sep); + if ValueOption("short") = true then + RemoveCharacters(s," "); + fi; return s; end); @@ -1759,27 +1763,29 @@ BindGlobal( "SD_cyclic", BindGlobal( "SD_cycsaspowers", # function to write C2 x C2 x C2 as 2^3, etc. function ( name, cycsizes ) - local short, g, d, k, j, n; + local g, d, k, j, n; - short := ValueOption("short") = true; - if not short then return name; fi; + if ValueOption("short") <> true then + return name; + fi; RemoveCharacters(name," "); - cycsizes := Collected(cycsizes); - for n in cycsizes do - d := n[1]; k := n[2]; - g := SD_cyclic(d); - if d = 0 then - d := "Z"; - else - d := String(d); - fi; - if k > 1 then - for j in Reversed([2..k]) do - name := ReplacedString(name,SD_insertsep(List([1..j],i->g),"x",""), - Concatenation(d,"^",String(j))); - od; - fi; - od; + cycsizes := Collected(cycsizes); + for n in cycsizes do + d := n[1]; + k := n[2]; + g := SD_cyclic(d); + if d = 0 then + d := "Z"; + else + d := String(d); + fi; + if k > 1 then + for j in Reversed([2..k]) do + name := ReplacedString(name,SD_insertsep(List([1..j],i->g),"x",""), + Concatenation(d,"^",String(j))); + od; + fi; + od; RemoveCharacters(name,"C"); return name; end); @@ -1810,11 +1816,14 @@ BindGlobal( "StructureDescriptionForFiniteSimpleGroups", # for simple groups parameter; # parameters of G in series # special case abelian group - if IsAbelian(G) then return StructureDescriptionForAbelianGroups(G); fi; + if IsAbelian(G) then + return StructureDescriptionForAbelianGroups(G); + fi; # special case alternating group - if IsAlternatingGroup(G) - then return Concatenation("A",String(AlternatingDegree(G))); fi; + if IsAlternatingGroup(G) then + return Concatenation("A",String(AlternatingDegree(G))); + fi; # special case PSL if IsPSL(G) then @@ -1913,30 +1922,39 @@ BindGlobal( "StructureDescriptionForFiniteGroups", # for finite groups fi; # special case trivial group - if IsTrivial(G) then return "1"; fi; + if IsTrivial(G) then + return "1"; + fi; # special case abelian group - if IsAbelian(G) then return StructureDescriptionForAbelianGroups(G); fi; + if IsAbelian(G) then + return StructureDescriptionForAbelianGroups(G); + fi; # special case alternating group - if IsAlternatingGroup(G) - then return Concatenation("A",String(AlternatingDegree(G))); fi; + if IsAlternatingGroup(G) then + return Concatenation("A",String(AlternatingDegree(G))); + fi; # special case symmetric group - if IsSymmetricGroup(G) - then return Concatenation("S",String(SymmetricDegree(G))); fi; + if IsSymmetricGroup(G) then + return Concatenation("S",String(SymmetricDegree(G))); + fi; # special case dihedral group - if IsDihedralGroup(G) and Size(G) > 6 - then return Concatenation("D",String(Size(G))); fi; + if IsDihedralGroup(G) and Size(G) > 6 then + return Concatenation("D",String(Size(G))); + fi; # special case quaternion group - if IsQuaternionGroup(G) - then return Concatenation("Q",String(Size(G))); fi; + if IsQuaternionGroup(G) then + return Concatenation("Q",String(Size(G))); + fi; # special case quasidihedral group - if IsQuasiDihedralGroup(G) - then return Concatenation("QD",String(Size(G))); fi; + if IsQuasiDihedralGroup(G) then + return Concatenation("QD",String(Size(G))); + fi; # special case PSL if IsPSL(G) then @@ -1975,7 +1993,9 @@ BindGlobal( "StructureDescriptionForFiniteGroups", # for finite groups cycsizes := Filtered(cycsizes,n->n<>1); cycname := SD_cycsaspowers(SD_insertsep(List(cycsizes, SD_cyclic), " x ",":."), cycsizes); - else cycname := ""; fi; + else + cycname := ""; + fi; noncyclics := Difference(Gs,cyclics); noncycname := SD_insertsep(List(noncyclics,StructureDescription), " x ",":."); @@ -2049,32 +2069,33 @@ BindGlobal( "StructureDescriptionForFiniteGroups", # for finite groups # non-splitting, non-simple group if not IsTrivial(Centre(G)) then cname := SD_insertsep([StructureDescription(Centre(G)), - StructureDescription(G/Centre(G))]," . ","x:."); + StructureDescription(G/Centre(G))], + " . ","x:."); fi; if not IsPerfectGroup(G) then dname := SD_insertsep([StructureDescription(DerivedSubgroup(G)), StructureDescription(G/DerivedSubgroup(G))], " . ","x:."); fi; - if IsBound(cname) and IsBound(dname) and cname <> dname - then return Concatenation(cname," = ",dname); - elif IsBound(cname) then return cname; - elif IsBound(dname) then return dname; - elif not IsTrivial(FrattiniSubgroup(G)) - then return SD_insertsep([StructureDescription(FrattiniSubgroup(G)), - StructureDescription(G/FrattiniSubgroup(G))], - " . ","x:."); - elif IsPosInt(NrPerfectGroups(Size(G))) - and not Size(G) in [ 86016, 368640, 737280 ] - # this does not happen for Size(G)<10^6 - then - id := PerfectIdentification(G); - return Concatenation("PerfectGroup(",String(id[1]),",", - String(id[2]),")"); - else return Concatenation(""); + if IsBound(cname) and IsBound(dname) and cname <> dname then + return Concatenation(cname," = ",dname); + elif IsBound(cname) then + return cname; + elif IsBound(dname) then + return dname; + elif not IsTrivial(FrattiniSubgroup(G)) then + return SD_insertsep([StructureDescription(FrattiniSubgroup(G)), + StructureDescription(G/FrattiniSubgroup(G))], + " . ","x:."); + elif IsPosInt(NrPerfectGroups(Size(G))) then + id := PerfectIdentification(G); + return Concatenation("PerfectGroup(",String(id[1]),",", + String(id[2]),")"); + else + return Concatenation(""); fi; end ); From 1c6c7ffb8484f46b95d63e4ae1fb1ea1a030f0ef Mon Sep 17 00:00:00 2001 From: Michael Young Date: Sat, 23 May 2026 11:43:07 +0100 Subject: [PATCH 013/114] Add new logo to banner (B&W) (#6357) --- lib/init.g | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/init.g b/lib/init.g index 03601c810a..a4b64c169d 100644 --- a/lib/init.g +++ b/lib/init.g @@ -434,7 +434,7 @@ function( prefix, values, suffix ) end); BindGlobal( "ShowKernelInformation", function() - local sysdate, btop, vert, bbot, config, str, gap; + local sysdate, btop, bmid, bbot, config, str, gap; if GAPInfo.Date <> "today" then sysdate := " of "; @@ -447,19 +447,24 @@ BindGlobal( "ShowKernelInformation", function() fi; if GAPInfo.TermEncoding = "UTF-8" then - btop := "┌───────┐\c"; vert := "│"; bbot := "└───────┘\c"; + btop := " ● G"; + bmid := "● ● A"; + bbot := " ● P"; else - btop := "*********"; vert := "*"; bbot := btop; + btop := " o G"; + bmid := "o o A"; + bbot := " o P"; fi; if IsHPCGAP then gap := "HPC-GAP"; else gap := "GAP"; fi; - Print( " ",btop," ",gap," ", GAPInfo.BuildVersion, + Print( " ",btop," ",gap," ", GAPInfo.BuildVersion, sysdate, "\n", - " ",vert," GAP ",vert," https://www.gap-system.org\n", - " ",bbot," Architecture: ", GAPInfo.Architecture, "\n" ); + " ",bmid," https://www.gap-system.org\n", + " ",bbot," Architecture: ", GAPInfo.Architecture, "\n", + "\n" ); if IsHPCGAP then Print( " Maximum concurrent threads: ", GAPInfo.KernelInfo.NUM_CPUS, "\n"); From 707c955cb05a381f027b49f80c36a8c58de48501 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 23 May 2026 12:45:10 +0200 Subject: [PATCH 014/114] Switch banner to fully compact mode ... as discussed on PR #6357 --- lib/init.g | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/init.g b/lib/init.g index a4b64c169d..82c828d242 100644 --- a/lib/init.g +++ b/lib/init.g @@ -463,8 +463,7 @@ BindGlobal( "ShowKernelInformation", function() Print( " ",btop," ",gap," ", GAPInfo.BuildVersion, sysdate, "\n", " ",bmid," https://www.gap-system.org\n", - " ",bbot," Architecture: ", GAPInfo.Architecture, "\n", - "\n" ); + " ",bbot," Architecture: ", GAPInfo.Architecture, "\n" ); if IsHPCGAP then Print( " Maximum concurrent threads: ", GAPInfo.KernelInfo.NUM_CPUS, "\n"); From 8a57deac61f41684a2e553326f685a0aeb440174 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 26 May 2026 14:36:33 +0200 Subject: [PATCH 015/114] Turn LoadPackageDocumentation into a unary function (#6411) This undocumented function accepted more than one argument, but ignored any beyond the first. Apparently this was introduced in the GAP 4.5 days for compatibility reasons? But compatibility with what? No package known to me calls this. For reference in GAP 4.4 it had two arguments (but also was undocumented, and not called by any outside code). --- lib/package.gi | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/package.gi b/lib/package.gi index a4b404027e..b23272e685 100644 --- a/lib/package.gi +++ b/lib/package.gi @@ -1396,15 +1396,8 @@ InstallGlobalFunction( RereadPackage, function( arg ) ## #F LoadPackageDocumentation( ) ## -## In versions before 4.5, a second argument was required. -## For the sake of backwards compatibility, we do not forbid a second -## argument, but we ignore it. -## (In later versions, we may forbid the second argument.) -## -InstallGlobalFunction( LoadPackageDocumentation, function( arg ) - local info, short, pkgdoc, long, sixfile; - - info:= arg[1]; +InstallGlobalFunction( LoadPackageDocumentation, function( info ) + local short, pkgdoc, long, sixfile; # Load all books for the package. for pkgdoc in info.PackageDoc do From b49098af514632adc27536d534009552939d244f Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Tue, 26 May 2026 05:37:37 -0700 Subject: [PATCH 016/114] doc: describe OrbitStabilizer return value (closes #6324) (#6410) The OrbitStabilizer entry in the reference manual only documented the algorithm, not what the operation returns. Adds: - A short sentence explicitly stating the return value is an immutable record with `orbit` (the orbit as a list) and `stabilizer` (the point stabilizer subgroup of G). - A small example block using the same `g:=Group((1,3,2),(2,4,3));;` setup already used by the adjacent `Stabilizer` example, so the rendered output is identical to verified output already in this file. --- lib/oprt.gd | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/oprt.gd b/lib/oprt.gd index 20bae46045..e75a76cc81 100644 --- a/lib/oprt.gd +++ b/lib/oprt.gd @@ -1550,8 +1550,22 @@ OrbitsishOperation( "OrbitLengthsDomain", OrbitsishReq, false, NewAttribute ); ## ## computes the orbit and the stabilizer of pnt simultaneously in a ## single orbit-stabilizer algorithm. +## Returns an immutable record with components orbit (the orbit as +## a list) and stabilizer (the point stabilizer, a subgroup of +## G). ##

## The stabilizer will have G as its parent. +## g:=Group((1,3,2),(2,4,3));; +## gap> orbstab:=OrbitStabilizer(g,[1,2],OnSets); +## rec( +## orbit := [ [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 2, 3 ], [ 3, 4 ], +## [ 2, 4 ] ], stabilizer := Group([ (1,2)(3,4) ]) ) +## gap> orbstab.orbit; +## [ [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 2, 3 ], [ 3, 4 ], [ 2, 4 ] ] +## gap> orbstab.stabilizer; +## Group([ (1,2)(3,4) ]) +## ]]> ## ## ## <#/GAPDoc> From 2fd8c101d204a2c434dcdf3ba7ce36e9b23eea37 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 27 May 2026 08:07:19 +0200 Subject: [PATCH 017/114] Run --bare testinstall test in CI (#6354) --- .github/workflows/CI.yml | 2 +- dev/ci.sh | 4 ++++ tst/testinstall/maxsub.tst | 4 ++++ tst/testinstall/package.tst | 11 +++++++++-- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ca0f05b997..0159bdcfb8 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -47,7 +47,7 @@ jobs: test-suites: [ # base test: fast first test - "testinstall", + "testinstall-bare", "teststandard", diff --git a/dev/ci.sh b/dev/ci.sh index e45ca39268..170a346368 100755 --- a/dev/ci.sh +++ b/dev/ci.sh @@ -422,6 +422,10 @@ GAPInput ;; + testinstall-bare) + $GAP $(gap_cover_arg) --bare $SRCDIR/tst/testinstall.g + ;; + *) if [[ ! -f $SRCDIR/tst/${TEST_SUITE}.g ]] then diff --git a/tst/testinstall/maxsub.tst b/tst/testinstall/maxsub.tst index 036381d657..e04103b67b 100644 --- a/tst/testinstall/maxsub.tst +++ b/tst/testinstall/maxsub.tst @@ -9,12 +9,14 @@ gap> SortedList(List(msc, IndexInParent)); [ 2, 3, 4 ] # +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> G := GL(2,4);; gap> msc:=MaximalSubgroupClassReps(G);; gap> ForAll(msc, H -> Parent(H) = G); true gap> SortedList(List(msc, IndexInParent)); [ 3, 5, 6, 10 ] +#@fi # gap> G := GL(2,5);; @@ -25,10 +27,12 @@ gap> SortedList(List(msc, IndexInParent)); [ 2, 5, 6, 10 ] # +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> G := AlternatingGroup(5);; gap> msc := MaximalSubgroupClassReps(G);; gap> SortedList(List(msc, H -> Index(G, H))); [ 5, 6, 10 ] +#@fi # gap> STOP_TEST("maxsub.tst"); diff --git a/tst/testinstall/package.tst b/tst/testinstall/package.tst index 48df3fbf39..1ccd238478 100644 --- a/tst/testinstall/package.tst +++ b/tst/testinstall/package.tst @@ -435,9 +435,11 @@ false gap> IsPackageLoaded("mockpkg", ">=2.0"); false +# # instruct GAP to load the package, and record all its declarations # the help book of mockpkg might already have been loaded in other tests # -> we suppress a warning about this +#@if IsPackageMarkedForLoading( "gapdoc", "" ) gap> old_warning_level := InfoLevel( InfoWarning );; gap> SetInfoLevel( InfoWarning, 0 ); gap> PackageVariablesInfo("mockpkg", "0.1");; @@ -481,9 +483,14 @@ gap> IsDateFormatValid := function( datestring ) > end;; gap> IsDateFormatValid( GAPInfo.Date ); true +#@else +gap> LoadPackage("mockpkg", false); +oops, should not print here +true +#@fi # Test the Cite() command (output changed with GAPDoc 1.6.6 and again with 1.6.7) -#@if CompareVersionNumbers(InstalledPackageVersion("gapdoc"), "1.6.7") +#@if IsPackageMarkedForLoading( "gapdoc", "1.6.7" ) gap> Cite("mockpkg"); Please use one of the following samples to cite mockpkg version from this installation @@ -538,7 +545,7 @@ rg/}}}, } -#@else +#@elif IsPackageMarkedForLoading( "gapdoc", "" ) gap> Cite("mockpkg"); Please use one of the following samples to cite mockpkg version from this installation From 06bb20bf5b603a6ae5a0dbb4dc68dc779ab2bd97 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 27 May 2026 15:34:33 +0200 Subject: [PATCH 018/114] Prepare release notes for GAP 4.16.0 (#6414) --- CHANGES.md | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 6f4c6c84a9..48c602ec6b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,194 @@ # GAP - history of changes +## GAP 4.16.0 (May 2026) + +The following gives an overview of the changes compared to the previous +release. This list is not complete, many more internal or minor changes +were made, but we tried to only list those changes which we think might +affect some users directly. + +### New features + +- [#6384](https://github.com/gap-system/gap/pull/6384) Add `EnumeratorOfPartitionsSet` enumerator +- [#6322](https://github.com/gap-system/gap/pull/6322) Add `IsGenericMatrixRep` matrix object type +- [#6311](https://github.com/gap-system/gap/pull/6311) Add `PositionNonZeroInRow` for matrices and matrix objects +- [#6277](https://github.com/gap-system/gap/pull/6277) Add `DirectSumGModule` +- [#6268](https://github.com/gap-system/gap/pull/6268) Add `IsSquareMat` and `IsAntisymmetricMat` +- [#6262](https://github.com/gap-system/gap/pull/6262) Add `UserHomeShorten` as counterpart of `UserHomeExpand` +- [#6261](https://github.com/gap-system/gap/pull/6261) Add `WhereDepth` user preference to control depth of initial stack trace in break loops +- [#6259](https://github.com/gap-system/gap/pull/6259) Add `IsSymmetricMatrix` (and `IsSymmetricMat` as a synonym) +- [#6232](https://github.com/gap-system/gap/pull/6232) Add `RandomMatrix`, `RandomInvertibleMatrix`; and fix a problem with a new feature for matrix groups +- [#6213](https://github.com/gap-system/gap/pull/6213) Add `ConformalSymplecticGroup` +- [#5980](https://github.com/gap-system/gap/pull/5980) Add `AddMatrix`, `MultMatrix` (plus explicit left/right side variants) for in-place modification of matrices +- [#3357](https://github.com/gap-system/gap/pull/3357) Add `FoldLeft`, `FoldLeftX`; and `ForAllX`, `ForAnyX`, `FilteredX`, `NumberX`, `PerformX` to complement `ListX`, `SetX`, `SumX`, `ProductX` + +### Performance improvements + +- [#6398](https://github.com/gap-system/gap/pull/6398) Speed up conversion from integers to finite field elements +- [#6329](https://github.com/gap-system/gap/pull/6329) Speed up `CopySubMatrix`, `CopySubVector`, `ExtractSubMatrix`, `ExtractSubVector` for plist matrices/vectors +- [#6289](https://github.com/gap-system/gap/pull/6289) Make the meataxe faster by using `AddMatrix`, `AddVector`, `MultMatrix`, `MultVector` +- [#6276](https://github.com/gap-system/gap/pull/6276) Faster high-level Meataxe functions for irreducible modules (e.g. `MTX.IsomorphismModules`, `MTX.Indecomposition`, `MTX.BasisModuleEndomorphisms`, `MTX.BasisModuleHomomorphisms`) +- [#6267](https://github.com/gap-system/gap/pull/6267) Improve conjugation test for subgroups with different orders +- [#6265](https://github.com/gap-system/gap/pull/6265) Speed up `IsSubset` for cyclotomic domains (such as `Integers`, `PositiveIntegers`, `GaussianRationals` etc.) +- [#6114](https://github.com/gap-system/gap/pull/6114) Enhance support for very long transversals in a permutation group by forcing down huge index steps through an intermediate subgroup + +### Improved and extended functionality + +- [#6357](https://github.com/gap-system/gap/pull/6357) Update the GAP banner to reflect the new GAP logo +- [#6338](https://github.com/gap-system/gap/pull/6338) Improve `CosetLeadersMatFFE` documentation +- [#6334](https://github.com/gap-system/gap/pull/6334) Translating a range by adding an integer now produces another range (instead of a plain list) when possible +- [#6320](https://github.com/gap-system/gap/pull/6320) Add a manual section on how to write code for matrix objects +- [#6309](https://github.com/gap-system/gap/pull/6309) Allow `CopySubVector` on plain row vectors, fix `CopySubMatrix` +- [#6292](https://github.com/gap-system/gap/pull/6292) Document new `PackageInfo.g` fields `Dependencies.TestPackages` and `Dependencies.NeededSystemPackages`, and teach `ValidatePackageInfo` about them +- [#6280](https://github.com/gap-system/gap/pull/6280) Implement `MultVectorRight` for lists +- [#6257](https://github.com/gap-system/gap/pull/6257) Improve break-loop stack traces to be more consistent, provide more information and to indicate the current environment selected via `DownEnv`/`UpEnv` +- [#6211](https://github.com/gap-system/gap/pull/6211) Improve documentation for nice monomorphisms +- [#6183](https://github.com/gap-system/gap/pull/6183) Transfer more properties (such as `IsNaturalSL`, `InvariantQuadraticForm` etc.) when conjugating matrix groups + +### Removed or obsolete functionality + +- [#6067](https://github.com/gap-system/gap/pull/6067) Deprecate `InstallValue` for anything but plain objects (i.e., plain GAP lists, records or strings) and warn if it is done anyway + +### Changes related to handling of packages + +- [#6191](https://github.com/gap-system/gap/pull/6191) Remove unused "PC STACK" variables for from the left collectors (this breaks compatibility with polycyclic version 2.16 and older; use 2.17 or newer instead) + +### Changes in the documentation + +- [#6410](https://github.com/gap-system/gap/pull/6410) Document `OrbitStabilizer` return value +- [#6408](https://github.com/gap-system/gap/pull/6408) Document `SemiSimpleType` field restriction +- [#6405](https://github.com/gap-system/gap/pull/6405) Clarify `IsomorphismPcGroup` docs +- [#6370](https://github.com/gap-system/gap/pull/6370) Improve documentation of `OnTuplesSets`, `OnSetsDisjointSets`, `OnSetsTuples` +- [#6361](https://github.com/gap-system/gap/pull/6361) Simplify the list of `Matrix` argument variants in the manual +- [#6348](https://github.com/gap-system/gap/pull/6348) Clarify `CompatiblePairs` documentation +- [#6337](https://github.com/gap-system/gap/pull/6337) Clarify `IrreducibleModules` description to say 'at most' dim +- [#6260](https://github.com/gap-system/gap/pull/6260) Document `DirectProductElement` +- [#6220](https://github.com/gap-system/gap/pull/6220) Correct the documentation of `NewFamily` +- [#6198](https://github.com/gap-system/gap/pull/6198) Document setter for mutable attributes +- [#6174](https://github.com/gap-system/gap/pull/6174) Document objects with memory +- [#6171](https://github.com/gap-system/gap/pull/6171) Improve documentation of `InverseGeneralMapping` +- [#6169](https://github.com/gap-system/gap/pull/6169) Fix the definition of `PClassPGroup` +- [#6162](https://github.com/gap-system/gap/pull/6162) Only show authors in `Cite`, not maintainers + +### Fixed bugs that could lead to incorrect results + +- [#6382](https://github.com/gap-system/gap/pull/6382) Fix `Irr` for natural symmetric groups when the conjugacy classes are ordered differently in the group and its character table +- [#6358](https://github.com/gap-system/gap/pull/6358) Fix `HexSHA256` to always return 64 hex digits and not drop leading zero digits +- [#6341](https://github.com/gap-system/gap/pull/6341) Fix return value of `PartitionsGreatestLE(0, m)` and improve its documentation +- [#6340](https://github.com/gap-system/gap/pull/6340) Fix `MinimalGeneratingSet` for pc groups which sometimes returned incorrect (non-minimal) results +- [#6325](https://github.com/gap-system/gap/pull/6325) Fix garbled result produced by `CosetLeadersMatFFE` +- [#6303](https://github.com/gap-system/gap/pull/6303) Fix `CopySubVector` for GF(2) vectors to not produce invalid results for certain inputs +- [#6253](https://github.com/gap-system/gap/pull/6253) Fix `ShortestVectors` with `"positive"` argument returning a potentially incomplete list +- [#6245](https://github.com/gap-system/gap/pull/6245) Fix `PreImagesRepresentative` for group homomorphisms with `OnLines` action +- [#6206](https://github.com/gap-system/gap/pull/6206) Fix two bugs in `IsomorphismPermGroupForMatrixGroup` +- [#6203](https://github.com/gap-system/gap/pull/6203) Fix `FieldOfMatrixGroup` for certain classical matrix groups in dimension up to 2, and fix related problems with their invariant forms +- [#6170](https://github.com/gap-system/gap/pull/6170) Fix `IsomorphismPermGroup` for trivial f. p. (sub)group +- [#6160](https://github.com/gap-system/gap/pull/6160) Fix a bug in `RepresentativesPerfectSubgroups` that could lead to the omission of subgroups + +### Fixed bugs that could lead to crashes + +- [#6326](https://github.com/gap-system/gap/pull/6326) Fix crash in `CosetLeadersMatFFE` + +### Fixed bugs that could lead to unexpected errors + +- [#6196](https://github.com/gap-system/gap/pull/6196) Fix an inconsistency problem in `IsFinite` for matrix groups over cycl. fields. +- [#6159](https://github.com/gap-system/gap/pull/6159) Fix a potential error message about data types when computing extensions + +### Other fixed bugs + +- [#6355](https://github.com/gap-system/gap/pull/6355) Reset the options stack after an error also when the break loop is disabled (`-T` command line option) +- [#6218](https://github.com/gap-system/gap/pull/6218) Change `CoverageLineByLine` to produce output compatible with that produced by the `--coverage` command line option + +### Other changes + +- [#6230](https://github.com/gap-system/gap/pull/6230) Make `RestrictedMapping` of a group homomorphism use the same `Range` as the original morphism + +### Package distribution + +#### New packages redistributed with GAP + +- [**ClassicalMaximals**](https://gap-packages.github.io/ClassicalMaximals/) 1.1: Maximal subgroups of classical groups, by Maximilian Hauck, Max Horn, Tristan Pfersdorff, Christian Seeger, Sergio Siccha +- [**LocalNR**](https://gap-packages.github.io/LocalNR) 2.1.0: Package of local nearrings, by Iryna Raievska, Maryna Raievska, Yaroslav Sysak +- [**ModularGroup**](https://ag-weitze-schmithusen.github.io/ModularGroup) 2.0.2: Finite-index subgroups of (P)SL(2,Integers), by Sebastian Engelhardt, Luca Leon Junk, Hannah Wagmann, Gabriela Weitze-Schmithüsen +- [**nofoma**](https://gap-packages.github.io/nofoma) 1.0.1: Normal forms of matrices, by Meinolf Geck, Alia Bonnet +- [**Origami**](https://AG-Weitze-Schmithusen.github.io/Origami/) 2.0.3: Computing Veech groups of origamis, by Leo Emmerich, Sebastian Engelhardt, Simon Ertl, Luca Leon Junk, Pascal Kattler, Alexander Rogovskyy, Pascal Schumann, Andrea Thevis, Hannah Wagmann, Gabriela Weitze-Schmithüsen +- [**PackageMaker**](https://gap-packages.github.io/PackageMaker) 1.0.1: A GAP package for creating new GAP packages, by Max Horn + +#### Updated packages redistributed with GAP + +The GAP 4.16.0 distribution contains 172 packages, of which 68 have been +updated since GAP 4.15.1. The full list of updated packages is given below: + +- [**4ti2Interface**](https://homalg-project.github.io/pkg/4ti2Interface): 2024.11-01 -> 2025.12-01 +- [**Alnuth**](https://gap-packages.github.io/alnuth): 3.2.1 -> 4.0.0 +- [**ANUPQ**](https://gap-packages.github.io/anupq/): 3.3.2 -> 3.3.3 +- [**AtlasRep**](https://www.math.rwth-aachen.de/~Thomas.Breuer/atlasrep): 2.1.9 -> 2.1.11 +- [**AutoDoc**](https://gap-packages.github.io/AutoDoc): 2025.10.16 -> 2026.05.11 +- [**AutPGrp**](https://gap-packages.github.io/autpgrp/): 1.11.1 -> 1.12.0 +- [**Browse**](https://www.math.rwth-aachen.de/~Browse): 1.8.21 -> 1.8.22 +- [**CAP**](https://homalg-project.github.io/pkg/CAP): 2025.09-04 -> 2026.05-08 +- [**CaratInterface**](https://www.math.uni-bielefeld.de/~gaehler/gap/packages.php): 2.3.7 -> 2.3.9 +- [**CddInterface**](https://homalg-project.github.io/CddInterface): 2025.06.24 -> 2026.03.02 +- [**Cryst**](https://www.math.uni-bielefeld.de/~gaehler/gap/packages.php): 4.1.30 -> 4.1.31 +- [**CrystCat**](https://www.math.uni-bielefeld.de/~gaehler/gap/packages.php): 1.1.10 -> 1.1.11 +- [**curlInterface**](https://gap-packages.github.io/curlInterface/): 2.4.2 -> 2.4.3 +- [**cvec**](https://gap-packages.github.io/cvec): 2.8.4 -> 2.8.5 +- [**datastructures**](https://gap-packages.github.io/datastructures): 0.4.0 -> 0.4.1 +- [**Digraphs**](https://digraphs.github.io/Digraphs): 1.13.1 -> 1.14.0 +- [**ExamplesForHomalg**](https://homalg-project.github.io/pkg/ExamplesForHomalg): 2023.10-01 -> 2025.12-01 +- [**ferret**](https://gap-packages.github.io/ferret/): 1.0.15 -> 1.0.16 +- [**FORMAT**](https://gap-packages.github.io/format/): 1.4.4 -> 1.4.5 +- [**Forms**](https://gap-packages.github.io/forms): 1.2.13 -> 1.3.0 +- [**FPLSA**](https://gap-packages.github.io/FPLSA): 1.2.7 -> 1.2.8 +- [**GAPDoc**](https://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc): 1.6.7 -> 1.6.10 +- [**Gauss**](https://homalg-project.github.io/pkg/Gauss): 2024.11-01 -> 2025.12-01 +- [**GaussForHomalg**](https://homalg-project.github.io/pkg/GaussForHomalg): 2024.08-01 -> 2026.04-01 +- [**GeneralizedMorphismsForCAP**](https://homalg-project.github.io/pkg/GeneralizedMorphismsForCAP): 2025.08-01 -> 2025.12-01 +- [**GradedModules**](https://homalg-project.github.io/pkg/GradedModules): 2024.12-01 -> 2026.04-01 +- [**GradedRingForHomalg**](https://homalg-project.github.io/pkg/GradedRingForHomalg): 2024.07-01 -> 2026.04-01 +- [**groupoids**](https://gap-packages.github.io/groupoids/): 1.79 -> 1.81 +- [**GUAVA**](https://gap-packages.github.io/guava): 3.20 -> 3.21 +- [**HAP**](https://gap-packages.github.io/hap): 1.70 -> 1.75 +- [**HAPcryst**](https://gap-packages.github.io/hapcryst/): 0.1.15 -> 0.2.0 +- [**HeLP**](https://gap-packages.github.io/HeLP): 4.0 -> 4.1 +- [**homalg**](https://homalg-project.github.io/pkg/homalg): 2024.01-01 -> 2025.12-01 +- [**HomalgToCAS**](https://homalg-project.github.io/pkg/HomalgToCAS): 2025.08-01 -> 2026.04-01 +- [**IBNP**](https://gap-packages.github.io/ibnp/): 0.17 -> 0.18 +- [**IO_ForHomalg**](https://homalg-project.github.io/pkg/IO_ForHomalg): 2023.02-04 -> 2025.12-01 +- [**json**](https://gap-packages.github.io/json/): 2.2.3 -> 2.4.0 +- [**LinearAlgebraForCAP**](https://homalg-project.github.io/pkg/LinearAlgebraForCAP): 2025.09-01 -> 2026.05-04 +- [**LocalizeRingForHomalg**](https://homalg-project.github.io/pkg/LocalizeRingForHomalg): 2023.10-01 -> 2026.04-01 +- [**lpres**](https://gap-packages.github.io/lpres): 1.1.1 -> 1.1.2 +- [**matgrp**](https://www.math.colostate.edu/~hulpke/matgrp): 0.72 -> 0.73 +- [**MatricesForHomalg**](https://homalg-project.github.io/pkg/MatricesForHomalg): 2025.09-01 -> 2026.04-01 +- [**ModIsom**](https://gap-packages.github.io/modisom/): 3.0.0 -> 3.1.0 +- [**ModulePresentationsForCAP**](https://homalg-project.github.io/pkg/ModulePresentationsForCAP): 2025.09-01 -> 2026.04-01 +- [**Modules**](https://homalg-project.github.io/pkg/Modules): 2024.12-01 -> 2026.04-01 +- [**MonoidalCategories**](https://homalg-project.github.io/pkg/MonoidalCategories): 2025.08-02 -> 2026.05-02 +- [**NConvex**](https://homalg-project.github.io/pkg/NConvex): 2024.12-01 -> 2025.12-02 +- [**NormalizInterface**](https://gap-packages.github.io/NormalizInterface): 1.4.1 -> 1.5.1 +- [**orb**](https://gap-packages.github.io/orb): 5.0.1 -> 5.1.0 +- [**Polycyclic**](https://gap-packages.github.io/polycyclic/): 2.17 -> 2.18 +- [**polymaking**](https://gap-packages.github.io/polymaking/): 0.8.7 -> 0.8.9 +- [**PrimGrp**](https://gap-packages.github.io/primgrp/): 4.0.1 -> 4.0.2 +- [**qpa**](https://gap-packages.github.io/qpa): 1.35 -> 1.37 +- [**RCWA**](https://gap-packages.github.io/rcwa/): 4.8.0 -> 4.9.0 +- [**recog**](https://gap-packages.github.io/recog): 1.4.4 -> 1.5.1 +- [**RingsForHomalg**](https://homalg-project.github.io/pkg/RingsForHomalg): 2024.11-02 -> 2025.12-01 +- [**SCO**](https://homalg-project.github.io/pkg/SCO): 2023.08-01 -> 2025.12-01 +- [**Semigroups**](https://semigroups.github.io/Semigroups): 5.5.4 -> 5.6.3 +- [**singular**](https://gap-packages.github.io/singular/): 2025.08.26 -> 2026.05.05 +- [**SmallClassNr**](https://stertooy.github.io/SmallClassNr): 1.4.2 -> 1.5.1 +- [**ToolsForHomalg**](https://homalg-project.github.io/pkg/ToolsForHomalg): 2025.05-01 -> 2026.04-01 +- [**TwistedConjugacy**](https://stertooy.github.io/TwistedConjugacy): 3.1.1 -> 3.3.2 +- [**typeset**](https://gap-packages.github.io/typeset/): 1.2.3 -> 1.2.4 +- [**utils**](https://gap-packages.github.io/utils): 0.92 -> 0.95 +- [**walrus**](https://gap-packages.github.io/walrus): 0.9991 -> 0.9992 +- [**Wedderga**](https://gap-packages.github.io/wedderga): 4.11.1 -> 4.11.3 +- [**XMod**](https://gap-packages.github.io/xmod/): 2.95 -> 2.98 +- [**ZeroMQInterface**](https://gap-packages.github.io/ZeroMQInterface/): 0.17 -> 0.18 + + ## GAP 4.15.1 (October 2025) The following gives an overview of the changes compared to the previous From f14734d8c50b54fcfb7ffcd2fbc63e6dfe1db52e Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 27 May 2026 15:44:06 +0200 Subject: [PATCH 019/114] Start work on GAP 4.17 --- CITATION | 14 +++++++------- configure.ac | 2 +- doc/versiondata | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CITATION b/CITATION index 906d89e6a5..bcd784c127 100644 --- a/CITATION +++ b/CITATION @@ -2,23 +2,23 @@ Please use one of the following samples to cite GAP version from this installati Text: -[GAP] GAP – Groups, Algorithms, and Programming, Version 4.16dev, +[GAP] GAP – Groups, Algorithms, and Programming, Version 4.17dev, The GAP Group (this year), https://www.gap-system.org. HTML:

[GAP] - GAP – Groups, Algorithms, and Programming, Version 4.16dev, + GAP – Groups, Algorithms, and Programming, Version 4.17dev, The GAP Group (this year), https://www.gap-system.org.

BibXML: - + <C>GAP</C> – <C>G</C>roups, <C>A</C>lgorithms, - and <C>P</C>rogramming, <C>V</C>ersion 4.16dev + and Programming, Version 4.17dev https://www.gap-system.org this year GAP @@ -28,8 +28,8 @@ BibXML: BibTeX: -@misc{ GAP4.16dev, - title = {{GAP} {\textendash} {G}roups, {A}lgorithms, and {P}rogramming, {V}ersion 4.16dev}, +@misc{ GAP4.17dev, + title = {{GAP} {\textendash} {G}roups, {A}lgorithms, and {P}rogramming, {V}ersion 4.17dev}, organization = {The GAP {G}roup}, year = {this year}, howpublished = {\href{https://www.gap-system.org}{\texttt{https://www.gap-system.org}}}, @@ -41,7 +41,7 @@ If you are not using BibTeX, here is the bibliography entry produced by BibTeX (in bibliography style `alpha'): \bibitem[GAP]{GAP4} -\emph{GAP -- Groups, Algorithms, and Programming}, Version 4.16dev, +\emph{GAP -- Groups, Algorithms, and Programming}, Version 4.17dev, The GAP~Group (this year), \verb+https://www.gap-system.org+. If you have (predominantly) used one or more particular GAP packages, diff --git a/configure.ac b/configure.ac index 1c313ffb8a..9320f18ce0 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl Setup autoconf dnl AC_PREREQ([2.68]) -m4_define([gap_version], [4.16dev]) +m4_define([gap_version], [4.17dev]) m4_define([gap_releaseday], [today]) m4_define([gap_releaseyear], [this year]) diff --git a/doc/versiondata b/doc/versiondata index 98c2758afa..a2eec48b00 100644 --- a/doc/versiondata +++ b/doc/versiondata @@ -4,7 +4,7 @@ Instead edit either the template file `doc/versiondata.in`, or edit `Makefile.rules` (which has code for generating this file), or edit `configure.ac` (where the value being substituted come from) --> - + - + From 9f5c520b7e0e1da2fd9a9fec49b3080f256a875f Mon Sep 17 00:00:00 2001 From: Christopher Jefferson Date: Mon, 1 Jun 2026 19:40:53 +0800 Subject: [PATCH 020/114] emscripten: add Docker-based one-stop build and polish demo page (#6385) Rework the emscripten build into a reproducible flow inside a pinned container: etc/emscripten/build-in-docker.sh builds the image, runs the wasm build, and assembles a self-contained web-example/ that can be copied to any static host. Replaces the previous mix of shell, Ruby and Node helpers. The toolchain is pinned to emsdk 3.1.23 because both halves of the REPL are sensitive to the exact version: GASMAN's conservative GC, and xterm-pty's emscriptenHack() patching emscripten's TTY device so tcsetattr() reaches the line discipline. 3.1.23 is the version that works with the pinned xterm-pty 0.9.4; a newer emsdk leaves tcsetattr unhonoured and double- echoes typed input. See the Dockerfile for the full rationale. Build robustness fixes, independent of the toolchain version: - configure zlib with --static (newer wasm-ld rejects its shared .so test targets; GAP only needs libz.a); - remove the generated src/c_*.c and ffdata.* before the native build so reruns regenerate them instead of failing; - assemble-website.sh copies the data tree resiliently (some packages ship dangling .dSYM symlinks that aborted the copy and left lib/, grp/ uncopied, causing startup 404s), drops pkg/log/ test logs, ships gap.worker.js only if the build produced one, and asserts lib/init.g landed in the output. Also fix the outdated documentation links in the demo page and refresh startup_manifest.json. AI assistance: Claude Code (Opus 4.8) was used to make these changes. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitignore | 11 + etc/emscripten/Dockerfile | 50 + etc/emscripten/README.md | 127 +- etc/emscripten/assemble-website.sh | 64 + etc/emscripten/build-in-docker.sh | 80 ++ etc/emscripten/build.sh | 152 ++- etc/emscripten/build_startup_manifest.js | 71 - etc/emscripten/generate_gap_fs_json.py | 25 +- etc/emscripten/run-web-demo.sh | 13 - etc/emscripten/serve.py | 35 + etc/emscripten/server.rb | 15 - etc/emscripten/startup_manifest.json | 1521 ++++++++++++++++++++++ etc/emscripten/web-template/gap-fs.js | 51 +- etc/emscripten/web-template/index.html | 181 ++- src/gasman.c | 4 +- 15 files changed, 2191 insertions(+), 209 deletions(-) create mode 100644 etc/emscripten/Dockerfile create mode 100755 etc/emscripten/assemble-website.sh create mode 100755 etc/emscripten/build-in-docker.sh delete mode 100755 etc/emscripten/build_startup_manifest.js delete mode 100755 etc/emscripten/run-web-demo.sh create mode 100755 etc/emscripten/serve.py delete mode 100755 etc/emscripten/server.rb create mode 100644 etc/emscripten/startup_manifest.json diff --git a/.gitignore b/.gitignore index 5d67442b54..ca50cf4952 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,17 @@ /libgap*.dll* /libgap*.so* +# emscripten / wasm build outputs (etc/emscripten/build.sh and friends) +/native-build/ +/extern/emscripten/ +/web-example/ +/packages.tar.gz +/gap.html +/gap.js +/gap.wasm +/gap.worker.js +/gap-fs.json + /bin/gap*.sh /bin/*-*/ # Compiling the `xgap` package creates the file `xgap.sh` diff --git a/etc/emscripten/Dockerfile b/etc/emscripten/Dockerfile new file mode 100644 index 0000000000..9025dbaaa3 --- /dev/null +++ b/etc/emscripten/Dockerfile @@ -0,0 +1,50 @@ +# Build environment for compiling GAP to WebAssembly via Emscripten. +# +# Pinned to emsdk 3.1.23 for reproducibility. Both pieces of the in-browser +# REPL are sensitive to the exact toolchain version: +# +# - GASMAN, GAP's conservative garbage collector, scans the stack including +# pointers held in wasm registers, reached via emscripten_scan_registers() +# (see src/gasman.c). That path is now compiled correctly regardless of +# version, so the GC itself is no longer the constraint. +# +# - The terminal uses xterm-pty, whose emscriptenHack() monkey-patches +# emscripten's internal TTY device so GAP's tcsetattr() (turning off echo +# and canonical mode) reaches the line discipline. That patch is tied to +# emscripten's TTY internals: on 3.1.47 the ioctl no longer reaches +# xterm-pty, echo stays on, and every typed line is echoed twice. +# +# 3.1.23 is the version where the pinned xterm-pty (0.9.4) works. Bump both +# together and re-test the REPL -- including that typed input is not +# double-echoed -- before changing this. + +FROM emscripten/emsdk:3.1.23 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + autoconf \ + automake \ + libtool \ + make \ + python3 \ + ca-certificates \ + curl \ + bison \ + byacc \ + m4 \ + && rm -rf /var/lib/apt/lists/* + +# Allow running as a non-root host UID without breaking the emscripten cache. +RUN mkdir -p /emsdk/upstream/emscripten/cache \ + && chmod -R 0777 /emsdk/upstream/emscripten/cache + +# Cache the GAP package distribution tarball so container runs don't +# re-download it from GitHub each time. The URL pins to the "latest" +# release on the PackageDistro side, so this snapshot drifts as upstream +# tags new releases — rebuild the image (--no-cache) to refresh. +ARG GAP_PACKAGES_URL=https://github.com/gap-system/PackageDistro/releases/download/latest/packages.tar.gz +RUN curl --fail --location --silent --show-error \ + --output /opt/gap-packages.tar.gz \ + "$GAP_PACKAGES_URL" \ + && chmod 0644 /opt/gap-packages.tar.gz + +WORKDIR /gap diff --git a/etc/emscripten/README.md b/etc/emscripten/README.md index 5946302efe..083de668b6 100644 --- a/etc/emscripten/README.md +++ b/etc/emscripten/README.md @@ -1,26 +1,127 @@ -Code to allow building gap to WASM using Emscripten. +# GAP in the browser -Files: +Build GAP as a WebAssembly module and serve it as a self-contained website. +The terminal interface uses [xterm-pty](https://github.com/mame/xterm-pty), +so the resulting page behaves like a normal GAP REPL. -- `build.sh`: Run as `etc/emscripten/build.sh` from a fresh copy of GAP. +## Quick start -- `web-template`: Uses 'xterm-pty' to create a "nice" interface to the Wasm GAP. +From a fresh GAP checkout, with either Docker or Podman installed: -- `build_startup_manifest.js`: Run it in the web root directory to build `startup_manifest.json` that contains resources to preload. +```sh +etc/emscripten/build-in-docker.sh +cd web-example +../etc/emscripten/serve.py +``` + +Then open . The first build takes 10–30 minutes; the +docker image, the GAP package distribution, and the GMP/zlib builds are all +cached for subsequent runs. + +To pick up newer GAP packages from upstream, force a fresh image build: + +```sh +docker build --no-cache -t gap-emscripten-build:3.1.23 etc/emscripten/ +``` + +On Apple Silicon (and other non-amd64 hosts), the build runs `linux/amd64` +under emulation, since `emscripten/emsdk:3.1.23` is amd64-only on Docker +Hub. `build-in-docker.sh` pins the platform explicitly so the layer cache +holds across runs; set `BUILD_PLATFORM` to override. + +The output directory `web-example/` is fully self-contained — copy it to any +static host (see "Hosting" below for the headers it needs). + +## Building without Docker + +If you already have emsdk 3.1.23 sourced in your shell, you can run the +underlying build directly: + +```sh +etc/emscripten/build.sh +etc/emscripten/assemble-website.sh +``` + +emsdk 3.1.23 is the version we test against, paired with xterm-pty 0.9.4. +GAP relies on ASYNCIFY together with GASMAN's conservative GC, which scans +wasm registers via `emscripten_scan_registers()` (see `src/gasman.c`); and +the terminal relies on xterm-pty's `emscriptenHack()` patching emscripten's +TTY device so `tcsetattr()` reaches the line discipline. Both are sensitive +to the toolchain version (a newer emsdk leaves `tcsetattr` unhonoured, so +typed input is echoed twice), so re-test the REPL when changing emsdk. -See 'run-web-demo.sh' as an example on how to set up a working website. +## Hosting -Note that this demo uses xterm-pty, a library which provides a terminal interface -for emscripten-compiled programs. This uses a javascript feature called -"SharedArrayBuffer", which requires some headers are returned by the server: +The xterm-pty terminal uses `SharedArrayBuffer`, which browsers only allow +when the page is served with these two headers: ``` Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp ``` -For more details, see for [this article](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer). +`serve.py` is a 20-line stdlib-only Python server that adds them. For +GitHub Pages and other static hosts that don't let you set headers, +`web-template/coi-serviceworker.js` is included as a workaround (it +re-fetches resources through a service worker that adds the headers). + +## Files + +| File | Role | +| ---- | ---- | +| `build-in-docker.sh` | One-stop entry point. Builds the image, runs `build.sh` inside, then `assemble-website.sh`. | +| `Dockerfile` | Pinned `emscripten/emsdk:3.1.23` with autotools, python3, bison/byacc/m4, and a baked-in copy of the GAP package distribution tarball at `/opt/gap-packages.tar.gz`. | +| `build.sh` | Configures and builds GMP, zlib, and GAP itself for wasm. | +| `assemble-website.sh` | Copies the build outputs and data directories (`pkg`, `lib`, `grp`, …) into `web-example/`. | +| `generate_gap_fs_json.py` | Reads file paths on stdin, writes `gap-fs.json` (the manifest of every file in the virtual FS). | +| `startup_manifest.json` | List of files to fetch eagerly at startup, captured from a real GAP run. Anything not in this list is fetched lazily on first read. See "Updating the startup manifest" below for how to refresh it. | +| `serve.py` | Local server that adds the COOP/COEP headers. | +| `web-template/` | Static UI: `index.html`, the worker scripts, the FS init shim, and the COOP/COEP service worker for hosts where you can't set headers. | + +## Updating the startup manifest + +`startup_manifest.json` lists files (relative to the GAP root) that the FS +init shim downloads up front instead of lazily. The current list was +captured from a real GAP run reaching its prompt, so it includes both +the core library bootstrap (`lib/init.g`, `lib/read*.g`, …) and any +default-loaded packages. Entries that no longer exist in the build are +silently ignored, so it is safe to leave stale entries in place; it is +also safe to leave the list empty (every file becomes lazy). + +The manifest is a startup-time optimisation, not a correctness mechanism: +a wrong list never breaks the build, it only makes startup slower (files +GAP needs but the manifest omits get fetched lazily, one round-trip each) +or wastes bandwidth (files in the manifest that GAP doesn't actually +read are downloaded anyway). So it's worth refreshing when something +changes the set of files read at startup — most importantly when the +default loaded packages change, but also after large library reshuffles. + +To regenerate it after such changes: + +1. Build the website (`build-in-docker.sh`) and serve it (`serve.py`). +2. **Empty the served manifest before capturing.** Replace + `web-example/startup_manifest.json` with `[]` (or delete it). + Otherwise the existing entries are eagerly pre-fetched at startup, + appear in `fetchedUrls`, and you'll just round-trip the old list. + Editing the served file is enough — no rebuild is needed. +3. Open the page and wait for the GAP prompt to appear. Every file that + GAP actually reads now goes through the lazy `XHR` path and gets + captured. +4. Open devtools and read the captured URLs from the page's JS console: + `window.fetchedUrls` is an array of every unique URL the worker + requested. Chrome/Firefox provide a `copy()` console helper: + `copy(JSON.stringify(fetchedUrls))` puts the JSON on your clipboard. +5. Strip non-GAP-FS entries (`gap.js`, `gap.wasm`, `gap-fs.json`, the + xterm CDN URLs) and write the result to + `etc/emscripten/startup_manifest.json` (so it's checked in and gets + picked up by the next `assemble-website.sh`). A `jq` filter that + keeps just GAP filesystem paths: + + ```sh + jq '[.[] | select(test("^(pkg|lib|grp|tst|doc|hpcgap|dev|benchmark)/"))]' \ + fetched-urls.json > etc/emscripten/startup_manifest.json + ``` -The file "coi-serviceworker.js" works around this problem on Github pages. This won't -work locally, so "server.rb" is a simple ruby script, which just starts a web-server -which returns the required headers. \ No newline at end of file +The bookkeeping lives in `web-template/gap-fs.js` (wraps `fetch` and +`XMLHttpRequest.open` to report URLs to the main thread) and +`web-template/index.html` (accumulates them onto `window.fetchedUrls`). diff --git a/etc/emscripten/assemble-website.sh b/etc/emscripten/assemble-website.sh new file mode 100755 index 0000000000..12e6f6a83b --- /dev/null +++ b/etc/emscripten/assemble-website.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +# +# Assemble a self-contained website from a completed wasm build. +# Outputs ./web-example/ relative to the GAP source root. +# +# Run after etc/emscripten/build.sh (or have build-in-docker.sh call it). + +set -euo pipefail + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +ROOT_DIR=$(cd "$SCRIPT_DIR/../.." && pwd) +OUT_DIR="$ROOT_DIR/web-example" + +cd "$ROOT_DIR" + +for f in gap.js gap.wasm gap-fs.json; do + if [[ ! -f $f ]]; then + echo "Error: missing build output '$f'. Run etc/emscripten/build.sh first." >&2 + exit 1 + fi +done + +# Always start from a clean output directory. Merging into a previous +# web-example/ confuses cp when a tree has changed shape between runs +# (e.g. pkg/X switching between a symlink and a real directory). +rm -rf "$OUT_DIR" +mkdir -p "$OUT_DIR" + +cp "$SCRIPT_DIR"/web-template/* "$OUT_DIR"/ +cp "$SCRIPT_DIR"/startup_manifest.json "$OUT_DIR"/ +cp gap.js gap.wasm gap-fs.json "$OUT_DIR"/ +# Emscripten only emits a separate gap.worker.js for pthread builds; this +# single-threaded ASYNCIFY build doesn't use one (newer emscripten inlines +# the worker regardless). Copy it only if it was produced. +if [[ -f gap.worker.js ]]; then + cp gap.worker.js "$OUT_DIR"/ +fi +cp LICENSE COPYRIGHT "$OUT_DIR"/ + +# Data directories. These are referenced by gap-fs.json and either eagerly +# loaded (if listed in startup_manifest.json) or lazily fetched on first +# read by Emscripten's createLazyFile. +# +# -L dereferences symlinks so the output tree is self-contained (a setup +# where pkg/X is a symlink into a separate checkout still works). Some +# packages ship dangling symlinks as build artefacts (e.g. pkg/vole's +# rust/target/*.dSYM); cp prints those and exits non-zero but still copies +# everything else, so we don't let that abort the run. The assertion below +# catches a genuinely incomplete copy. +for d in pkg lib grp tst doc hpcgap dev benchmark; do + cp -RL "$d" "$OUT_DIR"/ 2>/dev/null || true +done + +# pkg/log holds package test logs (.log/.err/.out) that are never read at +# runtime; keep them out of the shipped site. +rm -rf "$OUT_DIR/pkg/log" + +# The library bootstrap must be present, or GAP 404s during startup. +if [[ ! -f "$OUT_DIR/lib/init.g" ]]; then + echo "Error: lib/init.g missing from $OUT_DIR after copy." >&2 + exit 1 +fi + +echo "Assembled website at $OUT_DIR" diff --git a/etc/emscripten/build-in-docker.sh b/etc/emscripten/build-in-docker.sh new file mode 100755 index 0000000000..ac7a7aa604 --- /dev/null +++ b/etc/emscripten/build-in-docker.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# +# One-stop shop: build GAP for the web inside a pinned container. +# +# Usage (run from the GAP source tree): +# etc/emscripten/build-in-docker.sh +# +# Output: ./web-example/ with a self-contained website. Copy it anywhere +# and serve with COOP/COEP headers (etc/emscripten/serve.py is one option). + +set -euo pipefail + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +ROOT_DIR=$(cd "$SCRIPT_DIR/../.." && pwd) + +RUNTIME="${CONTAINER_RUNTIME:-}" +if [[ -z "$RUNTIME" ]]; then + if command -v podman >/dev/null 2>&1; then + RUNTIME=podman + elif command -v docker >/dev/null 2>&1; then + RUNTIME=docker + else + echo "Error: neither podman nor docker found in PATH." >&2 + echo "Install one, or set CONTAINER_RUNTIME explicitly." >&2 + exit 1 + fi +fi + +IMAGE_TAG="gap-emscripten-build:3.1.23" + +# Pin the platform. emscripten/emsdk:3.1.23 is amd64-only on Docker Hub, so on +# Apple Silicon (or any non-amd64 host) the runtime would otherwise renegotiate +# the platform on every build -- that mismatch invalidates the FROM layer's +# cache and cascades through the whole image, defeating the layer cache even +# with --layers. Override with BUILD_PLATFORM if needed. +PLATFORM="${BUILD_PLATFORM:-linux/amd64}" + +echo ">> Using container runtime: $RUNTIME (platform: $PLATFORM)" +echo ">> Building image $IMAGE_TAG (cached after first run)" + +# --layers is the podman/buildah flag for "use the layer cache"; older +# podman versions default it to false. Docker has caching on by default +# and rejects the flag, so only pass it for podman. +declare -a BUILD_ARGS=(--platform "$PLATFORM") +if [[ "$RUNTIME" != "docker" ]]; then + BUILD_ARGS+=(--layers) +fi +"$RUNTIME" build "${BUILD_ARGS[@]}" -t "$IMAGE_TAG" -f "$SCRIPT_DIR/Dockerfile" "$SCRIPT_DIR" + +# Run as the host user where possible so build outputs are not root-owned. +declare -a USER_ARGS=() +if [[ "$RUNTIME" == "docker" ]]; then + USER_ARGS=(--user "$(id -u):$(id -g)" -e HOME=/tmp) +else + # Rootless podman maps host UID to container root by default. + USER_ARGS=(--userns=keep-id) +fi + +echo ">> Building GAP inside container" +"$RUNTIME" run --platform "$PLATFORM" --rm \ + -v "$ROOT_DIR:/gap" \ + -w /gap \ + "${USER_ARGS[@]}" \ + "$IMAGE_TAG" \ + bash etc/emscripten/build.sh + +echo ">> Assembling website" +bash "$SCRIPT_DIR/assemble-website.sh" + +cat </dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4) -if ! command -v emmake &> /dev/null; then - echo Please install, and source, emscripten - echo This script was tested with version 3.1.23 - echo See https://emscripten.org/docs/getting_started/downloads.html for install instructions +if ! command -v emmake >/dev/null 2>&1; then + echo "Please install and source emscripten." >&2 + echo "This script is tested with emsdk 3.1.23." >&2 + echo "See https://emscripten.org/docs/getting_started/downloads.html" >&2 exit 1 -fi; +fi # Build the configure script if this is a fresh git checkout if [[ ! -f ./configure ]]; then ./autogen.sh fi -# First build a standard GAP install, for some files -# we will need during building +# First build a standard GAP install: we need ffgen and gap-nocomp on the +# host to generate sources that the wasm build cannot run itself. +# +# We copy those generated sources (build/c_*.c, build/ffdata.*) into src/ +# further down, so the wasm build picks them up as overrides. GAP's +# Makefile.rules, however, also treats src/c_oper1.c, src/ffdata.c etc. as +# overrides during THIS native build -- so leftovers from a previous run +# would stop the native build regenerating them in native-build/build/, and +# the copy below would then fail. Remove any leftovers so the native build +# regenerates them cleanly (keeps the script idempotent across re-runs). +rm -f src/c_oper1.c src/c_type1.c src/ffdata.c src/ffdata.h ( mkdir -p native-build cd native-build if [[ ! -f config.status ]]; then ../configure fi - make -j8 + make -j"$JOBS" ) AUX_BUILD=$PWD/extern/emscripten/build AUX_PREFIX=$PWD/extern/emscripten/install -mkdir -p "$AUX_BUILD" -mkdir -p "$AUX_PREFIX" +mkdir -p "$AUX_BUILD" "$AUX_PREFIX" +# A 32-bit build is required by GAP's small-integer representation, so we +# pin --build to i686-pc-linux-gnu. This may need revisiting if GAP ever +# moves to a 64-bit-friendly small-integer encoding. ( mkdir -p "$AUX_BUILD/gmp" - cd "$AUX_BUILD/gmp" && + cd "$AUX_BUILD/gmp" if [[ ! -f config.status ]]; then CC_FOR_BUILD=/usr/bin/gcc ABI=standard \ - emconfigure $BASEDIR/extern/gmp/configure \ - --build i686-pc-linux-gnu --host none \ - --disable-assembly --enable-cxx \ - --prefix=$AUX_PREFIX - fi && - emmake make -j8 && + emconfigure "$BASEDIR/extern/gmp/configure" \ + --build i686-pc-linux-gnu --host none \ + --disable-assembly --enable-cxx \ + --prefix="$AUX_PREFIX" + fi + emmake make -j"$JOBS" emmake make install ) ( mkdir -p "$AUX_BUILD/zlib" - cd "$AUX_BUILD/zlib" && + cd "$AUX_BUILD/zlib" if [[ ! -f Makefile ]]; then - emconfigure $BASEDIR/extern/zlib/configure --prefix=$AUX_PREFIX - fi; - emmake make -j8 && + # --static: skip the shared library. Newer emscripten's wasm-ld + # rejects linking zlib's .so test programs (examplesh) with + # "unknown file type: libz.so"; GAP only needs the static libz.a. + emconfigure "$BASEDIR/extern/zlib/configure" --static --prefix="$AUX_PREFIX" + fi + emmake make -j"$JOBS" emmake make install ) -# There are two problems with building GAP -# 1) GAP builds some executables (ffgen and gap-nocomp), which it wants to -# execute while building. We get these files from 'native-build'. -# 2) 'configure' gets confused by some of the LDFLAGS we need, so we have to pass -# them in to 'make' +# Two quirks of building GAP under emscripten: +# 1) GAP runs ffgen and gap-nocomp during the build. We copy the host-built +# versions in from native-build/ further down. +# 2) configure rejects some LDFLAGS we need at link time, so we pass them +# only at make-time. # -# These options are: -# -sASYNCIFY -- we don't care about ASYNC, but this forces the compiler to output -# all variables onto the stack, which is required for GASMAN -# Note we could use 'ALLOW_MEMORY_GROWTH', both we don't currently, we instead set -# a big memory window. -# -O2 : Some optimisation -# EXEEXT=.html -- this is actually a GAP makefile option, it lets us make the -# output 'gap.html', which makes emscripten output a html page we can load -# --pre-js lazy_fs.js : Prepend lazy_fs.js that is generated for lazy loading - -# Run configure if we don't have a makefile, or someone configured this -# GAP for standard building (emscripten builds will use 'emcc') -if [[ ! -f GNUmakefile ]] || ! grep '/emcc' GNUmakefile > /dev/null; then +# Link-time flags worth noting: +# -sASYNCIFY forces variables onto the stack (required by GASMAN). +# -O2 enables some optimisation. +# EXEEXT=.html a GAP makefile knob that produces gap.html, the html +# shim emscripten generates for loading the wasm module. + +if [[ ! -f GNUmakefile ]] || ! grep -q '/emcc' GNUmakefile; then + # Wipe any in-tree state from a prior native (or mismatched) build. + # Stale build/deps/*.d files reference build/ffdata.h, which under + # emcc would be regenerated by a non-executable JS shim; stale .o + # files have the wrong architecture. Configure regenerates build/. + rm -rf build ffgen emconfigure ./configure ABI=32 \ - --with-gmp=$AUX_PREFIX \ - --with-zlib=$AUX_PREFIX \ - LDFLAGS="-s ASYNCIFY=1 -O2" -fi; + --with-gmp="$AUX_PREFIX" \ + --with-zlib="$AUX_PREFIX" \ + LDFLAGS="-s ASYNCIFY=1 -O2" +fi -# Get full required packages -emmake make bootstrap-pkg-full +# Provide the GAP package distribution without re-downloading it on every +# build. Preference order: +# 1. An existing pkg/ directory. +# 2. packages.tar.gz already on the host (carried in the source mount). +# 3. The tarball baked into the docker image at /opt/gap-packages.tar.gz. +# 4. As a last resort, GAP's own bootstrap-pkg-full target downloads it. +# Skipping straight to tar avoids `bootstrap-pkg-full`, which calls +# curl -L -O unconditionally and overwrites packages.tar.gz on every run. +if [[ ! -d pkg ]]; then + if [[ ! -f packages.tar.gz && -f /opt/gap-packages.tar.gz ]]; then + cp /opt/gap-packages.tar.gz packages.tar.gz + fi + if [[ -f packages.tar.gz ]]; then + mkdir pkg + (cd pkg && tar xzf ../packages.tar.gz) + else + emmake make bootstrap-pkg-full + fi +fi -# Copy in files from native_build +# Copy host-built generated sources into place cp native-build/build/c_*.c native-build/build/ffdata.* src/ -# Dynamically find and append ALL required files to the JS array -# The flag -type f is safe because the only symbolic link is 'tst/mockpkg/Makefile.gappkg', -# which is safe to ignore -find pkg lib grp tst doc hpcgap dev benchmark -type f | python3 etc/emscripten/generate_gap_fs_json.py - -if [ $? -ne 0 ]; then - echo "Build aborted: generate_gap_fs_json.py failed." - exit 1 -fi +# Build the file list that will be served. -L follows symlinks so that +# users' local development setups (e.g. replacing pkg/foo with a symlink +# to a git checkout under git/foo) are picked up; -type f then drops any +# symlinks themselves. +find -L pkg lib grp tst doc hpcgap dev benchmark -type f ! -path 'pkg/log/*' \ + | python3 etc/emscripten/generate_gap_fs_json.py -# The EXEEXT is usually for windows, but here it lets us set GAP's extension, -# which lets us produce a html page to run GAP in. -emmake make -j8 LDFLAGS="-lidbfs.js -s ASYNCIFY=1 -sTOTAL_STACK=32mb -sASYNCIFY_STACK_SIZE=32000000 -sINITIAL_MEMORY=2048mb -O2" EXEEXT=".html" +emmake make -j"$JOBS" \ + LDFLAGS="-lidbfs.js -s ASYNCIFY=1 -sTOTAL_STACK=32mb -sASYNCIFY_STACK_SIZE=32000000 -sINITIAL_MEMORY=2048mb -O2" \ + EXEEXT=".html" diff --git a/etc/emscripten/build_startup_manifest.js b/etc/emscripten/build_startup_manifest.js deleted file mode 100755 index edb8594b10..0000000000 --- a/etc/emscripten/build_startup_manifest.js +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env node -"use strict"; - -const http = require('http'); -const fs = require('fs'); -const path = require('path'); - -const PORT = 9999; -const BASE_DIR = process.cwd(); -const LOG_FILE = path.join(BASE_DIR, 'startup_manifest.json'); - -const requestedFiles = new Set(); -fs.writeFileSync(LOG_FILE, '[\n]'); - -const server = http.createServer((req, res) => { - let urlPath = req.url.split('?')[0]; - if (urlPath === '/') { - urlPath = '/index.html'; - } - - let localDiskPath = urlPath; - try { - localDiskPath = decodeURIComponent(urlPath); - } catch (e) {} - - const filePath = path.join(BASE_DIR, localDiskPath); - - fs.readFile(filePath, (err, data) => { - if (err) { - console.error(`[404] Ignored missing file: ${localDiskPath}`); - res.writeHead(404); - res.end(`404: File not found`); - return; - } - - const ignored = ['/favicon.ico', '/index.html', '/startup_manifest.json', 'coi-serviceworker.js', 'gap-worker.js', 'gap-fs.js', 'gap.js', 'gap.wasm', 'gap-fs.json']; - if (!ignored.includes(localDiskPath)) { - let manifestPath = localDiskPath.startsWith('/') ? localDiskPath.substring(1) : localDiskPath; - - if (!requestedFiles.has(manifestPath)) { - requestedFiles.add(manifestPath); - - const manifest = Array.from(requestedFiles); - fs.writeFileSync(LOG_FILE, JSON.stringify(manifest, null, 4)); - - console.log(`[Loaded & Logged] ${manifestPath} (Total: ${requestedFiles.size})`); - } - } - - let contentType = 'application/octet-stream'; - if (urlPath.endsWith('.html')) contentType = 'text/html'; - else if (urlPath.endsWith('.js')) contentType = 'text/javascript'; - else if (urlPath.endsWith('.wasm')) contentType = 'application/wasm'; - else if (urlPath.endsWith('.css')) contentType = 'text/css'; - - res.writeHead(200, { - 'Content-Type': contentType, - 'Cross-Origin-Opener-Policy': 'same-origin', - 'Cross-Origin-Embedder-Policy': 'require-corp', - 'Access-Control-Allow-Origin': '*' - }); - - res.end(data); - }); -}); - -server.listen(PORT, '0.0.0.0', () => { - console.log(`\n Tracker running at http://localhost:${PORT}/`); - console.log(`Serving files from: ${BASE_DIR}`); - console.log(`Logging valid loaded files to: ${LOG_FILE}\n`); -}); diff --git a/etc/emscripten/generate_gap_fs_json.py b/etc/emscripten/generate_gap_fs_json.py index dbf5447bba..917f0a2a38 100755 --- a/etc/emscripten/generate_gap_fs_json.py +++ b/etc/emscripten/generate_gap_fs_json.py @@ -1,18 +1,11 @@ -import sys -import json -import os - -def main(): - paths = [line.strip() for line in sys.stdin if line.strip()] +#!/usr/bin/env python3 +"""Read a list of file paths from stdin (one per line) and write them as a +JSON array to gap-fs.json in the current directory.""" - try: - with open('gap-fs.json', 'w', encoding='utf-8') as f: - json.dump(paths, f, separators=(',', ':')) - - print(f"Successfully wrote {len(paths)} files to gap-fs.json", file=sys.stderr) - except Exception as e: - print(f"Failed to write gap-fs.json: {e}", file=sys.stderr) - sys.exit(1) +import json +import sys -if __name__ == "__main__": - main() +paths = [line.strip() for line in sys.stdin if line.strip()] +with open("gap-fs.json", "w", encoding="utf-8") as f: + json.dump(paths, f, separators=(",", ":")) +print(f"wrote {len(paths)} files to gap-fs.json", file=sys.stderr) diff --git a/etc/emscripten/run-web-demo.sh b/etc/emscripten/run-web-demo.sh deleted file mode 100755 index a82eb948a9..0000000000 --- a/etc/emscripten/run-web-demo.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -eux - -echo This script assumes you have already run 'build.sh' - -mkdir -p web-example -cp etc/emscripten/web-template/* web-example/ -cp gap.js gap.wasm gap.worker.js gap-fs.json web-example/ - -cp -r pkg lib grp tst doc hpcgap dev benchmark web-example/ -cd web-example -../etc/emscripten/server.rb diff --git a/etc/emscripten/serve.py b/etc/emscripten/serve.py new file mode 100755 index 0000000000..7d089f0c54 --- /dev/null +++ b/etc/emscripten/serve.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +"""Serve the current directory with the COOP/COEP headers required by +xterm-pty's SharedArrayBuffer usage. Run from the assembled web-example/ +(or any directory containing the gap.* artifacts). + + ./serve.py # listens on 8080 + ./serve.py 9000 # listens on 9000 +""" + +from __future__ import annotations + +import http.server +import socketserver +import sys + + +class CrossOriginIsolatedHandler(http.server.SimpleHTTPRequestHandler): + def end_headers(self): + self.send_header("Cross-Origin-Opener-Policy", "same-origin") + self.send_header("Cross-Origin-Embedder-Policy", "require-corp") + super().end_headers() + + +def main() -> None: + port = int(sys.argv[1]) if len(sys.argv) > 1 else 8080 + with socketserver.TCPServer(("", port), CrossOriginIsolatedHandler) as httpd: + print(f"Serving on http://localhost:{port}/ (Ctrl-C to stop)") + try: + httpd.serve_forever() + except KeyboardInterrupt: + print() + + +if __name__ == "__main__": + main() diff --git a/etc/emscripten/server.rb b/etc/emscripten/server.rb deleted file mode 100755 index 642c9ad167..0000000000 --- a/etc/emscripten/server.rb +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env ruby -# Taken from https://github.com/mame/xterm-pty/ - -require "webrick" - -class Server < WEBrick::HTTPServer - def service(req, res) - super - res["Cross-Origin-Opener-Policy"] = "same-origin" - res["Cross-Origin-Embedder-Policy"] = "require-corp" - end -end - -Server.new(Port: 8080, DocumentRoot: ".").start - diff --git a/etc/emscripten/startup_manifest.json b/etc/emscripten/startup_manifest.json new file mode 100644 index 0000000000..3ab701c269 --- /dev/null +++ b/etc/emscripten/startup_manifest.json @@ -0,0 +1,1521 @@ +[ + "lib/init.g", + "lib/kernel.g", + "lib/global.g", + "lib/system.g", + "lib/read1.g", + "lib/hpc/thread1.g", + "lib/filter.g", + "lib/oper.g", + "lib/oper1.g", + "lib/type.g", + "lib/type1.g", + "lib/methsel.g", + "lib/methsel2.g", + "lib/function.g", + "lib/cache.gd", + "lib/object.gd", + "lib/variable.g", + "lib/package.gd", + "lib/coll.gd", + "lib/list.gd", + "lib/wpobj.gd", + "lib/arith.gd", + "lib/ffe.gd", + "lib/domain.gd", + "lib/string.g", + "lib/cyclotom.g", + "lib/set.gd", + "lib/record.gd", + "lib/random.gd", + "lib/cache.gi", + "lib/coll.gi", + "lib/flag.g", + "lib/boolean.g", + "lib/ffe.g", + "lib/arith.gi", + "lib/list.g", + "lib/wpobj.g", + "lib/permutat.g", + "lib/trans.g", + "lib/pperm.g", + "lib/filter.gi", + "lib/object.gi", + "lib/listcoef.gd", + "lib/info.gd", + "lib/files.gd", + "lib/streams.gd", + "lib/record.gi", + "lib/matobj1.gd", + "lib/vecmat.gd", + "lib/vec8bit.gd", + "lib/mat8bit.gd", + "lib/global.gd", + "lib/info.gi", + "lib/global.gi", + "lib/options.gd", + "lib/options.gi", + "lib/attr.gd", + "lib/attr.gi", + "lib/string.gd", + "lib/userpref.g", + "lib/cmdledit.g", + "lib/cmdleditx.g", + "lib/objset.g", + "lib/float.gd", + "lib/macfloat.g", + "lib/hpc/tasks.g", + "lib/error.g", + "lib/session.g", + "lib/read2.g", + "lib/process.gd", + "lib/files.gi", + "lib/streams.gi", + "lib/process.gi", + "lib/read3.g", + "lib/type.gd", + "lib/tuples.gd", + "lib/rvecempt.gd", + "lib/extaset.gd", + "lib/extlset.gd", + "lib/extrset.gd", + "lib/extuset.gd", + "lib/dict.gd", + "lib/bitfields.gd", + "lib/mapping.gd", + "lib/mapphomo.gd", + "lib/relation.gd", + "lib/magma.gd", + "lib/mgmideal.gd", + "lib/mgmhom.gd", + "lib/mgmadj.gd", + "lib/mgmcong.gd", + "lib/semicong.gd", + "lib/semigrp.gd", + "lib/smgideal.gd", + "lib/monoid.gd", + "lib/grp.gd", + "lib/invsgp.gd", + "lib/addmagma.gd", + "lib/addcoset.gd", + "lib/semiring.gd", + "lib/ring.gd", + "lib/matrix.gd", + "lib/matint.gd", + "lib/matblock.gd", + "lib/ideal.gd", + "lib/module.gd", + "lib/basis.gd", + "lib/basismut.gd", + "lib/vspc.gd", + "lib/vspchom.gd", + "lib/zlattice.gd", + "lib/algebra.gd", + "lib/mgmring.gd", + "lib/algfp.gd", + "lib/alglie.gd", + "lib/algsc.gd", + "lib/alghom.gd", + "lib/liefam.gd", + "lib/algrep.gd", + "lib/lierep.gd", + "lib/integer.gd", + "lib/gaussian.gd", + "lib/numtheor.gd", + "lib/dlog.gd", + "lib/primality.gd", + "lib/contfrac.gd", + "lib/ringsc.gd", + "lib/ringhom.gd", + "lib/combinat.gd", + "lib/ratfun.gd", + "lib/fampred.g", + "lib/list.gi", + "lib/set.gi", + "lib/wpobj.gi", + "lib/random.gi", + "lib/field.gd", + "lib/zmodnz.gd", + "lib/zmodnze.gd", + "lib/cyclotom.gd", + "lib/fldabnum.gd", + "lib/padics.gd", + "lib/ringpoly.gd", + "lib/upoly.gd", + "lib/polyfinf.gd", + "lib/polyrat.gd", + "lib/polyconw.gd", + "lib/algfld.gd", + "lib/meataxe.gd", + "lib/unknown.gd", + "lib/word.gd", + "lib/wordass.gd", + "lib/matobj2.gd", + "lib/matobjplist.gd", + "lib/matobjnz.gd", + "lib/rws.gd", + "lib/rwspcclt.gd", + "lib/rwsgrp.gd", + "lib/rwspcgrp.gd", + "lib/groebner.gd", + "lib/pcgs.gd", + "lib/pcgsind.gd", + "lib/pcgspcg.gd", + "lib/pcgsmodu.gd", + "lib/pcgsperm.gd", + "lib/pcgsspec.gd", + "lib/grppc.gd", + "lib/grppcnrm.gd", + "lib/grptbl.gd", + "lib/grpperm.gd", + "lib/grpprmcs.gd", + "lib/stbcbckt.gd", + "lib/ghom.gd", + "lib/ghompcgs.gd", + "lib/gprd.gd", + "lib/ghomperm.gd", + "lib/gpprmsya.gd", + "lib/addgphom.gd", + "lib/grpnames.g", + "lib/grpnames.gd", + "lib/quotsys.gd", + "lib/pquot.gd", + "lib/oprt.gd", + "lib/partitio.gd", + "lib/stbc.gd", + "lib/clas.gd", + "lib/clashom.gd", + "lib/permdeco.gd", + "lib/csetgrp.gd", + "lib/factgrp.gd", + "lib/grpreps.gd", + "lib/grppcrep.gd", + "lib/onecohom.gd", + "lib/grppccom.gd", + "lib/twocohom.gd", + "lib/grppcext.gd", + "lib/grppcfp.gd", + "lib/randiso.gd", + "lib/schur.gd", + "lib/schursym.gd", + "lib/grplatt.gd", + "lib/oprtglat.gd", + "lib/grppclat.gd", + "lib/grppcaut.gd", + "lib/straight.gd", + "lib/memory.gd", + "lib/grpfp.gd", + "lib/grpfree.gd", + "lib/sgpres.gd", + "lib/tietze.gd", + "lib/ghomfp.gd", + "lib/dt.g", + "lib/integer.gi", + "lib/grpnice.gd", + "lib/morpheus.gd", + "lib/grpmat.gd", + "lib/fitfree.gd", + "lib/grpffmat.gd", + "lib/grpramat.gd", + "grp/basic.gd", + "grp/classic.gd", + "grp/conformal.gd", + "grp/perf.gd", + "grp/suzuki.gd", + "grp/ree.gd", + "grp/simple.gd", + "grp/imf.gd", + "grp/glzmodmz.gd", + "grp/clasmax.grp", + "lib/orders.gd", + "lib/trans.gd", + "lib/pperm.gd", + "lib/fastendo.gd", + "lib/fpsemi.gd", + "lib/fpmon.gd", + "lib/rwssmg.gd", + "lib/kbsemi.gd", + "lib/tcsemi.gd", + "lib/adjoin.gd", + "lib/semirel.gd", + "lib/semitran.gd", + "lib/reesmat.gd", + "lib/semiquo.gd", + "lib/semipperm.gd", + "lib/pager.gd", + "lib/helpbase.gd", + "lib/helpview.gd", + "lib/helpt2t.gd", + "lib/helpdef.gd", + "lib/ctbl.gd", + "lib/ctblfuns.gd", + "lib/ctblmaps.gd", + "lib/ctblauto.gd", + "lib/ctbllatt.gd", + "lib/ctblsymm.gd", + "lib/ctblsolv.gd", + "lib/ctblpope.gd", + "lib/ctblmoli.gd", + "lib/ctblmono.gd", + "lib/ctblgrp.gd", + "lib/tom.gd", + "lib/proto.gd", + "lib/gasman.gd", + "lib/memusage.gd", + "lib/read4.g", + "lib/profile.g", + "lib/newprofile.g", + "lib/methwhy.g", + "lib/pager.gi", + "lib/helpbase.gi", + "lib/helpview.gi", + "lib/helpt2t.gi", + "lib/helpdef.gi", + "lib/reread.g", + "lib/package.gi", + "lib/string.gi", + "lib/test.gd", + "lib/test.gi", + "lib/galois.gd", + "lib/galois.gi", + "lib/transatl.g", + "lib/obsolete.g", + "lib/obsolete.gd", + "lib/read.g", + "lib/read5.g", + "lib/type.gi", + "lib/rvecempt.gi", + "lib/ratfun1.gi", + "lib/matrix.gi", + "lib/matint.gi", + "lib/matblock.gi", + "lib/tuples.gi", + "lib/domain.gi", + "lib/mapping1.gi", + "lib/mapping.gi", + "lib/mapprep.gi", + "lib/mapphomo.gi", + "lib/relation.gi", + "lib/magma.gi", + "lib/mgmideal.gi", + "lib/mgmhom.gi", + "lib/mgmadj.gi", + "lib/mgmcong.gi", + "lib/semigrp.gi", + "lib/semicong.gi", + "lib/smgideal.gi", + "lib/monoid.gi", + "lib/grp.gi", + "lib/invsgp.gi", + "lib/addmagma.gi", + "lib/addcoset.gi", + "lib/ring.gi", + "lib/ideal.gi", + "lib/module.gi", + "lib/modfree.gi", + "lib/modulrow.gi", + "lib/modulmat.gi", + "lib/basis.gi", + "lib/basismut.gi", + "lib/vspc.gi", + "lib/vspcrow.gi", + "lib/vspcmat.gi", + "lib/vspchom.gi", + "lib/zlattice.gi", + "lib/mgmring.gi", + "lib/algebra.gi", + "lib/idealalg.gi", + "lib/alghom.gi", + "lib/algfp.gi", + "lib/alglie.gi", + "lib/algliess.gi", + "lib/algsc.gi", + "lib/algmat.gi", + "lib/liefam.gi", + "lib/algrep.gi", + "lib/lierep.gi", + "lib/numtheor.gi", + "lib/dlog.gi", + "lib/primality.gi", + "lib/contfrac.gi", + "lib/ringsc.gi", + "lib/ringhom.gi", + "lib/combinat.gi", + "lib/ratfun.gi", + "lib/ratfunul.gi", + "lib/ringpoly.gi", + "lib/upoly.gi", + "lib/upolyirr.gi", + "lib/polyfinf.gi", + "lib/polyrat.gi", + "lib/polyconw.gi", + "lib/listcoef.gi", + "lib/algfld.gi", + "lib/groebner.gi", + "lib/unknown.gi", + "lib/field.gi", + "lib/fieldfin.gi", + "lib/zmodnz.gi", + "lib/zmodnze.gi", + "lib/ffe.gi", + "lib/ffeconway.gi", + "lib/rational.gi", + "lib/gaussian.gi", + "lib/cyclotom.gi", + "lib/fldabnum.gi", + "lib/padics.gi", + "lib/matobj.gi", + "lib/matobjrowlist.gi", + "lib/vecmat.gi", + "lib/vec8bit.gi", + "lib/mat8bit.gi", + "lib/matobjplist.gi", + "lib/matobjnz.gi", + "lib/meataxe.gi", + "lib/meatauto.gi", + "lib/word.gi", + "lib/wordass.gi", + "lib/wordrep.gi", + "lib/wordlett.gi", + "lib/mgmfree.gi", + "lib/smgrpfre.gi", + "lib/monofree.gi", + "lib/grpfree.gi", + "lib/rws.gi", + "lib/rwspcclt.gi", + "lib/rwspcsng.gi", + "lib/rwspccoc.gi", + "lib/rwsgrp.gi", + "lib/rwspcgrp.gi", + "lib/rwsdt.gi", + "lib/nilpquot.gi", + "lib/pquot.gi", + "lib/pcgs.gi", + "lib/pcgsind.gi", + "lib/pcgsmodu.gi", + "lib/pcgspcg.gi", + "lib/pcgscomp.gi", + "lib/pcgsperm.gi", + "lib/pcgsnice.gi", + "lib/pcgsspec.gi", + "lib/grppc.gi", + "lib/grppcint.gi", + "lib/grppcprp.gi", + "lib/grppcatr.gi", + "lib/grppcnrm.gi", + "lib/bitfields.gi", + "lib/dict.gi", + "lib/dicthf.gi", + "lib/grptbl.gi", + "lib/ghom.gi", + "lib/ghompcgs.gi", + "lib/gprd.gi", + "lib/ghomperm.gi", + "lib/grpperm.gi", + "lib/gpprmsya.gi", + "lib/gprdperm.gi", + "lib/gprdpc.gi", + "lib/gprdmat.gi", + "lib/oprt.gi", + "lib/oprtperm.gi", + "lib/oprtpcgs.gi", + "lib/partitio.gi", + "lib/stbc.gi", + "lib/stbcbckt.gi", + "lib/stbcrand.gi", + "lib/clas.gi", + "lib/claspcgs.gi", + "lib/csetgrp.gi", + "lib/csetperm.gi", + "lib/csetpc.gi", + "lib/factgrp.gi", + "lib/grpreps.gi", + "lib/grppcrep.gi", + "lib/grpprmcs.gi", + "lib/grpnames.gi", + "lib/onecohom.gi", + "lib/grppccom.gi", + "lib/grpcompl.gi", + "lib/twocohom.gi", + "lib/grppcext.gi", + "lib/randiso.gi", + "lib/randiso2.gi", + "lib/grppcfp.gi", + "lib/schur.gi", + "lib/schursym.gi", + "lib/grpnice.gi", + "lib/fitfree.gi", + "lib/permdeco.gi", + "lib/clashom.gi", + "lib/clasperm.gi", + "lib/maxsub.gi", + "lib/norad.gi", + "lib/autsr.gi", + "lib/morpheus.gi", + "lib/grplatt.gi", + "lib/oprtglat.gi", + "lib/grppclat.gi", + "lib/grppcaut.gi", + "lib/grpmat.gi", + "lib/grpffmat.gi", + "lib/grpramat.gi", + "lib/grpfp.gi", + "lib/gpfpiso.gi", + "lib/sgpres.gi", + "lib/tietze.gi", + "lib/ghomfp.gi", + "lib/addgphom.gi", + "lib/trans.gi", + "lib/pperm.gi", + "lib/fastendo.gi", + "lib/fpsemi.gi", + "lib/fpmon.gi", + "lib/rwssmg.gi", + "lib/kbsemi.gi", + "lib/tcsemi.gi", + "lib/adjoin.gi", + "lib/semirel.gi", + "lib/semitran.gi", + "lib/reesmat.gi", + "lib/semiquo.gi", + "lib/semipperm.gi", + "lib/proto.gi", + "lib/orders.gi", + "lib/gasman.gi", + "lib/memusage.gi", + "lib/function.gi", + "lib/float.gi", + "lib/ieee754.g", + "lib/read6.g", + "grp/basicpcg.gi", + "grp/basicprm.gi", + "grp/basicmat.gi", + "grp/basicfp.gi", + "grp/perf.grp", + "grp/classic.gi", + "grp/conformal.gi", + "grp/suzuki.gi", + "grp/ree.gi", + "grp/simple.gi", + "grp/imf.grp", + "grp/imf.gi", + "grp/glzmodmz.gi", + "lib/read7.g", + "lib/ctbl.gi", + "lib/ctblfuns.gi", + "lib/ctblmaps.gi", + "lib/ctblauto.gi", + "lib/ctbllatt.gi", + "lib/ctblsymm.gi", + "lib/ctblsolv.gi", + "lib/ctblpope.gi", + "lib/ctblmoli.gi", + "lib/ctblmono.gi", + "lib/ctblgrp.gi", + "lib/ctblperm.gi", + "lib/ctblpc.gi", + "lib/tom.gi", + "lib/straight.gi", + "lib/memory.gi", + "lib/read8.g", + "lib/overload.g", + "lib/syntaxtree.gd", + "lib/syntaxtree.gi", + "lib/teaching.g", + "lib/teachm2.g", + "lib/operdebug.g", + "lib/colorprompt.g", + "pkg/4ti2interface/PackageInfo.g", + "pkg/ace/PackageInfo.g", + "pkg/aclib/PackageInfo.g", + "pkg/agt/PackageInfo.g", + "pkg/alco/PackageInfo.g", + "pkg/alnuth/PackageInfo.g", + "pkg/anupq/PackageInfo.g", + "pkg/atlasrep/PackageInfo.g", + "pkg/autodoc/PackageInfo.g", + "pkg/automata/PackageInfo.g", + "pkg/automgrp/PackageInfo.g", + "pkg/autpgrp/PackageInfo.g", + "pkg/browse/PackageInfo.g", + "pkg/cap/PackageInfo.g", + "pkg/caratinterface/PackageInfo.g", + "pkg/cddinterface/PackageInfo.g", + "pkg/circle/PackageInfo.g", + "pkg/classicalmaximals/PackageInfo.g", + "pkg/classicpres/PackageInfo.g", + "pkg/cohomolo/PackageInfo.g", + "pkg/congruence/PackageInfo.g", + "pkg/corefreesub/PackageInfo.g", + "pkg/corelg/PackageInfo.g", + "pkg/crime/PackageInfo.g", + "pkg/crisp/PackageInfo.g", + "pkg/crypting/PackageInfo.g", + "pkg/cryst/PackageInfo.g", + "pkg/crystcat/PackageInfo.g", + "pkg/ctbllib/PackageInfo.g", + "pkg/cubefree/PackageInfo.g", + "pkg/curlinterface/PackageInfo.g", + "pkg/cvec/PackageInfo.g", + "pkg/datastructures/PackageInfo.g", + "pkg/deepthought/PackageInfo.g", + "pkg/design/PackageInfo.g", + "pkg/difsets/PackageInfo.g", + "pkg/digraphs/PackageInfo.g", + "pkg/edim/PackageInfo.g", + "pkg/example/PackageInfo.g", + "pkg/examplesforhomalg/PackageInfo.g", + "pkg/factint/PackageInfo.g", + "pkg/ferret/PackageInfo.g", + "pkg/fga/PackageInfo.g", + "pkg/fining/PackageInfo.g", + "pkg/float/PackageInfo.g", + "pkg/format/PackageInfo.g", + "pkg/forms/PackageInfo.g", + "pkg/fplsa/PackageInfo.g", + "pkg/fr/PackageInfo.g", + "pkg/francy/PackageInfo.g", + "pkg/fwtree/PackageInfo.g", + "pkg/gapdoc/PackageInfo.g", + "pkg/gauss/PackageInfo.g", + "pkg/gaussforhomalg/PackageInfo.g", + "pkg/gbnp/PackageInfo.g", + "pkg/generalizedmorphismsforcap/PackageInfo.g", + "pkg/genss/PackageInfo.g", + "pkg/gradedmodules/PackageInfo.g", + "pkg/gradedringforhomalg/PackageInfo.g", + "pkg/grape/PackageInfo.g", + "pkg/groupoids/PackageInfo.g", + "pkg/grpconst/PackageInfo.g", + "pkg/guarana/PackageInfo.g", + "pkg/guava/PackageInfo.g", + "pkg/hap/PackageInfo.g", + "pkg/hapcryst/PackageInfo.g", + "pkg/hecke/PackageInfo.g", + "pkg/help/PackageInfo.g", + "pkg/homalg/PackageInfo.g", + "pkg/homalgtocas/PackageInfo.g", + "pkg/ibnp/PackageInfo.g", + "pkg/idrel/PackageInfo.g", + "pkg/images/PackageInfo.g", + "pkg/inducereduce/PackageInfo.g", + "pkg/intpic/PackageInfo.g", + "pkg/io/PackageInfo.g", + "pkg/io_forhomalg/PackageInfo.g", + "pkg/irredsol/PackageInfo.g", + "pkg/itc/PackageInfo.g", + "pkg/json/PackageInfo.g", + "pkg/jupyterkernel/PackageInfo.g", + "pkg/jupyterviz/PackageInfo.g", + "pkg/kan/PackageInfo.g", + "pkg/kbmag/PackageInfo.g", + "pkg/laguna/PackageInfo.g", + "pkg/liealgdb/PackageInfo.g", + "pkg/liepring/PackageInfo.g", + "pkg/liering/PackageInfo.g", + "pkg/linearalgebraforcap/PackageInfo.g", + "pkg/lins/PackageInfo.g", + "pkg/localizeringforhomalg/PackageInfo.g", + "pkg/localnr/PackageInfo.g", + "pkg/loops/PackageInfo.g", + "pkg/lpres/PackageInfo.g", + "pkg/majoranaalgebras/PackageInfo.g", + "pkg/mapclass/PackageInfo.g", + "pkg/matgrp/PackageInfo.g", + "pkg/matricesforhomalg/PackageInfo.g", + "pkg/modisom/PackageInfo.g", + "pkg/modulargroup/PackageInfo.g", + "pkg/modulepresentationsforcap/PackageInfo.g", + "pkg/modules/PackageInfo.g", + "pkg/monoidalcategories/PackageInfo.g", + "pkg/nconvex/PackageInfo.g", + "pkg/nilmat/PackageInfo.g", + "pkg/nock/PackageInfo.g", + "pkg/nofoma/PackageInfo.g", + "pkg/normalizinterface/PackageInfo.g", + "pkg/nq/PackageInfo.g", + "pkg/numericalsgps/PackageInfo.g", + "pkg/openmath/PackageInfo.g", + "pkg/orb/PackageInfo.g", + "pkg/origami/PackageInfo.g", + "pkg/packagemaker/PackageInfo.g", + "pkg/packagemanager/PackageInfo.g", + "pkg/patternclass/PackageInfo.g", + "pkg/permut/PackageInfo.g", + "pkg/polenta/PackageInfo.g", + "pkg/polycyclic/PackageInfo.g", + "pkg/polymaking/PackageInfo.g", + "pkg/primgrp/PackageInfo.g", + "pkg/profiling/PackageInfo.g", + "pkg/qdistrnd/PackageInfo.g", + "pkg/qpa/PackageInfo.g", + "pkg/quagroup/PackageInfo.g", + "pkg/radiroot/PackageInfo.g", + "pkg/rcwa/PackageInfo.g", + "pkg/rds/PackageInfo.g", + "pkg/recog/PackageInfo.g", + "pkg/repndecomp/PackageInfo.g", + "pkg/repsn/PackageInfo.g", + "pkg/resclasses/PackageInfo.g", + "pkg/ringsforhomalg/PackageInfo.g", + "pkg/sco/PackageInfo.g", + "pkg/scscp/PackageInfo.g", + "pkg/semigroups/PackageInfo.g", + "pkg/sglppow/PackageInfo.g", + "pkg/sgpviz/PackageInfo.g", + "pkg/simpcomp/PackageInfo.g", + "pkg/singular/PackageInfo.g", + "pkg/sl2reps/PackageInfo.g", + "pkg/sla/PackageInfo.g", + "pkg/smallantimagmas/PackageInfo.g", + "pkg/smallclassnr/PackageInfo.g", + "pkg/smallgrp/PackageInfo.g", + "pkg/smallsemi/PackageInfo.g", + "pkg/sonata/PackageInfo.g", + "pkg/sophus/PackageInfo.g", + "pkg/sotgrps/PackageInfo.g", + "pkg/spinsym/PackageInfo.g", + "pkg/standardff/PackageInfo.g", + "pkg/symbcompcc/PackageInfo.g", + "pkg/thelma/PackageInfo.g", + "pkg/tomlib/PackageInfo.g", + "pkg/toolsforhomalg/PackageInfo.g", + "pkg/toric/PackageInfo.g", + "pkg/transgrp/PackageInfo.g", + "pkg/twistedconjugacy/PackageInfo.g", + "pkg/typeset/PackageInfo.g", + "pkg/ugaly/PackageInfo.g", + "pkg/unipot/PackageInfo.g", + "pkg/unitlib/PackageInfo.g", + "pkg/utils/PackageInfo.g", + "pkg/uuid/PackageInfo.g", + "pkg/walrus/PackageInfo.g", + "pkg/wedderga/PackageInfo.g", + "pkg/wpe/PackageInfo.g", + "pkg/xgap/PackageInfo.g", + "pkg/xmod/PackageInfo.g", + "pkg/xmodalg/PackageInfo.g", + "pkg/yangbaxter/PackageInfo.g", + "pkg/zeromqinterface/PackageInfo.g", + "pkg/gapdoc/init.g", + "pkg/gapdoc/lib/UnicodeTools.gd", + "pkg/gapdoc/lib/PrintUtil.gd", + "pkg/gapdoc/lib/Text.gd", + "pkg/gapdoc/lib/ComposeXML.gd", + "pkg/gapdoc/lib/XMLParser.gd", + "pkg/gapdoc/lib/GAPDoc.gd", + "pkg/gapdoc/lib/BibTeX.gd", + "pkg/gapdoc/lib/BibXMLextTools.gd", + "pkg/gapdoc/lib/GAPDoc2LaTeX.gd", + "pkg/gapdoc/lib/GAPDoc2Text.gd", + "pkg/gapdoc/lib/GAPDoc2HTML.gd", + "pkg/gapdoc/lib/Make.g", + "pkg/gapdoc/lib/Examples.gd", + "pkg/gapdoc/read.g", + "pkg/gapdoc/lib/UnicodeTools.gi", + "pkg/gapdoc/lib/UnicodeTabs.g", + "pkg/gapdoc/lib/PrintUtil.gi", + "pkg/gapdoc/lib/Text.gi", + "pkg/gapdoc/lib/ComposeXML.gi", + "pkg/gapdoc/lib/XMLParser.gi", + "pkg/gapdoc/lib/gapdocdtdinfo.g", + "pkg/gapdoc/lib/GAPDoc.gi", + "pkg/gapdoc/lib/BibTeX.gi", + "pkg/gapdoc/lib/bibxmlextinfo.g", + "pkg/gapdoc/lib/BibXMLextTools.gi", + "pkg/gapdoc/lib/GAPDoc2LaTeX.gi", + "pkg/gapdoc/lib/latexhead.tex", + "pkg/gapdoc/lib/GAPDoc2Text.gi", + "pkg/gapdoc/lib/TextThemes.g", + "pkg/gapdoc/lib/GAPDoc2HTML.gi", + "pkg/gapdoc/lib/Examples.gi", + "pkg/gapdoc/lib/HelpBookHandler.g", + "pkg/primgrp/init.g", + "pkg/primgrp/lib/primitiv.gd", + "pkg/primgrp/lib/irredsol.gd", + "pkg/primgrp/read.g", + "pkg/primgrp/lib/primitiv.grp", + "pkg/primgrp/lib/primitiv.gi", + "pkg/primgrp/lib/irredsol.grp", + "pkg/primgrp/lib/irredsol.gi", + "pkg/primgrp/lib/cohorts.grp", + "pkg/smallgrp/init.g", + "pkg/smallgrp/gap/small.gd", + "pkg/smallgrp/read.g", + "pkg/smallgrp/gap/small.gi", + "pkg/smallgrp/gap/smlgp1.g", + "pkg/smallgrp/gap/idgrp1.g", + "pkg/smallgrp/gap/smlinfo.gi", + "pkg/smallgrp/small2/smlgp2.g.gz", + "pkg/smallgrp/small3/smlgp3.g.gz", + "pkg/smallgrp/small4/smlgp4.g.gz", + "pkg/smallgrp/small5/smlgp5.g.gz", + "pkg/smallgrp/small6/smlgp6.g.gz", + "pkg/smallgrp/small7/smlgp7.g.gz", + "pkg/smallgrp/small8/smlgp8.g.gz", + "pkg/smallgrp/small9/smlgp9.g.gz", + "pkg/smallgrp/small10/smlgp10.g.gz", + "pkg/smallgrp/small11/smlgp11.g.gz", + "pkg/smallgrp/id2/idgrp2.g.gz", + "pkg/smallgrp/id3/idgrp3.g.gz", + "pkg/smallgrp/id4/idgrp4.g.gz", + "pkg/smallgrp/id5/idgrp5.g.gz", + "pkg/smallgrp/id6/idgrp6.g.gz", + "pkg/smallgrp/id9/idgrp9.g.gz", + "pkg/smallgrp/id10/idgrp10.g.gz", + "pkg/transgrp/init.g", + "pkg/transgrp/lib/trans.gd", + "pkg/transgrp/read.g", + "pkg/transgrp/lib/trans.grp", + "pkg/transgrp/lib/trans.gi", + "pkg/autpgrp/init.g", + "pkg/autpgrp/gap/autos.gd", + "pkg/autpgrp/read.g", + "pkg/autpgrp/gap/general.gi", + "pkg/autpgrp/gap/autoops.gi", + "pkg/autpgrp/gap/matrix.gi", + "pkg/autpgrp/gap/nicestab.gi", + "pkg/autpgrp/gap/initmat.gi", + "pkg/autpgrp/gap/initperm.gi", + "pkg/autpgrp/gap/hybrstab.gi", + "pkg/autpgrp/gap/matrstab.gi", + "pkg/autpgrp/gap/orbstab.gi", + "pkg/autpgrp/gap/autos.gi", + "pkg/autpgrp/gap/pcpres.gi", + "pkg/autpgrp/gap/countcl.gi", + "pkg/alnuth/init.g", + "pkg/alnuth/gap/setup.gd", + "pkg/alnuth/gap/factors.gd", + "pkg/alnuth/gap/field.gd", + "pkg/polycyclic/init.g", + "pkg/polycyclic/gap/matrix/matrix.gd", + "pkg/polycyclic/gap/basic/infos.gd", + "pkg/polycyclic/gap/basic/collect.gd", + "pkg/polycyclic/gap/basic/pcpelms.gd", + "pkg/polycyclic/gap/basic/pcpgrps.gd", + "pkg/polycyclic/gap/basic/pcppcps.gd", + "pkg/polycyclic/gap/basic/grphoms.gd", + "pkg/polycyclic/gap/basic/basic.gd", + "pkg/polycyclic/gap/cohom/cohom.gd", + "pkg/polycyclic/gap/matrep/matrep.gd", + "pkg/polycyclic/gap/matrep/unitri.gd", + "pkg/polycyclic/gap/pcpgrp/pcpgrp.gd", + "pkg/polycyclic/gap/pcpgrp/torsion.gd", + "pkg/polycyclic/gap/exam/exam.gd", + "pkg/polycyclic/gap/obsolete.gd", + "pkg/alnuth/read.g", + "pkg/alnuth/gap/userpref.gi", + "pkg/alnuth/gap/setup.gi", + "pkg/alnuth/gap/pari.gi", + "pkg/alnuth/gap/factors.gi", + "pkg/alnuth/gap/matfield.gi", + "pkg/alnuth/gap/polfield.gi", + "pkg/alnuth/gap/field.gi", + "pkg/alnuth/gap/unithom.gi", + "pkg/alnuth/gap/matunits.gi", + "pkg/alnuth/gap/rels.gi", + "pkg/alnuth/gap/present.gi", + "pkg/alnuth/gap/isom.gi", + "pkg/alnuth/gap/rationals.gi", + "pkg/alnuth/exam/unimod.gi", + "pkg/alnuth/exam/rationals.gi", + "pkg/alnuth/exam/fields.gi", + "pkg/polycyclic/read.g", + "pkg/polycyclic/gap/matrix/rowbases.gi", + "pkg/polycyclic/gap/matrix/latbases.gi", + "pkg/polycyclic/gap/matrix/lattices.gi", + "pkg/polycyclic/gap/matrix/modules.gi", + "pkg/polycyclic/gap/matrix/triangle.gi", + "pkg/polycyclic/gap/matrix/hnf.gi", + "pkg/polycyclic/gap/basic/collect.gi", + "pkg/polycyclic/gap/basic/colftl.gi", + "pkg/polycyclic/gap/basic/colcom.gi", + "pkg/polycyclic/gap/basic/coldt.gi", + "pkg/polycyclic/gap/basic/colsave.gi", + "pkg/polycyclic/gap/basic/pcpelms.gi", + "pkg/polycyclic/gap/basic/pcppcps.gi", + "pkg/polycyclic/gap/basic/pcpgrps.gi", + "pkg/polycyclic/gap/basic/pcppara.gi", + "pkg/polycyclic/gap/basic/pcpexpo.gi", + "pkg/polycyclic/gap/basic/pcpsers.gi", + "pkg/polycyclic/gap/basic/grphoms.gi", + "pkg/polycyclic/gap/basic/pcpfact.gi", + "pkg/polycyclic/gap/basic/chngpcp.gi", + "pkg/polycyclic/gap/basic/convert.gi", + "pkg/polycyclic/gap/basic/orbstab.gi", + "pkg/polycyclic/gap/basic/construct.gi", + "pkg/polycyclic/gap/cohom/cohom.gi", + "pkg/polycyclic/gap/cohom/addgrp.gi", + "pkg/polycyclic/gap/cohom/general.gi", + "pkg/polycyclic/gap/cohom/solabel.gi", + "pkg/polycyclic/gap/cohom/solcohom.gi", + "pkg/polycyclic/gap/cohom/twocohom.gi", + "pkg/polycyclic/gap/cohom/intcohom.gi", + "pkg/polycyclic/gap/cohom/onecohom.gi", + "pkg/polycyclic/gap/cohom/grpext.gi", + "pkg/polycyclic/gap/cohom/grpcom.gi", + "pkg/polycyclic/gap/cohom/norcom.gi", + "pkg/polycyclic/gap/action/extend.gi", + "pkg/polycyclic/gap/action/basepcgs.gi", + "pkg/polycyclic/gap/action/freegens.gi", + "pkg/polycyclic/gap/action/dixon.gi", + "pkg/polycyclic/gap/action/kernels.gi", + "pkg/polycyclic/gap/action/orbstab.gi", + "pkg/polycyclic/gap/action/orbnorm.gi", + "pkg/polycyclic/gap/pcpgrp/general.gi", + "pkg/polycyclic/gap/pcpgrp/inters.gi", + "pkg/polycyclic/gap/pcpgrp/grpinva.gi", + "pkg/polycyclic/gap/pcpgrp/torsion.gi", + "pkg/polycyclic/gap/pcpgrp/maxsub.gi", + "pkg/polycyclic/gap/pcpgrp/findex.gi", + "pkg/polycyclic/gap/pcpgrp/nindex.gi", + "pkg/polycyclic/gap/pcpgrp/nilpot.gi", + "pkg/polycyclic/gap/pcpgrp/polyz.gi", + "pkg/polycyclic/gap/pcpgrp/pcpattr.gi", + "pkg/polycyclic/gap/pcpgrp/wreath.gi", + "pkg/polycyclic/gap/pcpgrp/fitting.gi", + "pkg/polycyclic/gap/pcpgrp/centcon.gi", + "pkg/polycyclic/gap/pcpgrp/normcon.gi", + "pkg/polycyclic/gap/pcpgrp/schur.gi", + "pkg/polycyclic/gap/pcpgrp/tensor.gi", + "pkg/polycyclic/gap/matrep/matrep.gi", + "pkg/polycyclic/gap/matrep/affine.gi", + "pkg/polycyclic/gap/matrep/unitri.gi", + "pkg/polycyclic/gap/exam/pcplib.gi", + "pkg/polycyclic/gap/exam/matlib.gi", + "pkg/polycyclic/gap/exam/nqlib.gi", + "pkg/polycyclic/gap/exam/generic.gi", + "pkg/polycyclic/gap/exam/bgnilp.gi", + "pkg/polycyclic/gap/exam/metacyc.gi", + "pkg/polycyclic/gap/exam/metagrp.gi", + "pkg/polycyclic/gap/cover/const/bas.gi", + "pkg/polycyclic/gap/cover/const/orb.gi", + "pkg/polycyclic/gap/cover/const/aut.gi", + "pkg/polycyclic/gap/cover/const/com.gi", + "pkg/polycyclic/gap/cover/const/cov.gi", + "pkg/crisp/init.g", + "pkg/crisp/lib/classes.gd", + "pkg/crisp/lib/grpclass.gd", + "pkg/crisp/lib/fitting.gd", + "pkg/crisp/lib/schunck.gd", + "pkg/crisp/lib/form.gd", + "pkg/crisp/lib/projector.gd", + "pkg/crisp/lib/injector.gd", + "pkg/crisp/lib/normpro.gd", + "pkg/crisp/lib/solveeq.gd", + "pkg/crisp/lib/compl.gd", + "pkg/crisp/lib/radical.gd", + "pkg/crisp/lib/residual.gd", + "pkg/crisp/lib/util.gd", + "pkg/crisp/lib/samples.gd", + "pkg/crisp/lib/socle.gd", + "pkg/crisp/read.g", + "pkg/crisp/lib/classes.gi", + "pkg/crisp/lib/grpclass.gi", + "pkg/crisp/lib/fitting.gi", + "pkg/crisp/lib/schunck.gi", + "pkg/crisp/lib/form.gi", + "pkg/crisp/lib/projector.gi", + "pkg/crisp/lib/injector.gi", + "pkg/crisp/lib/normpro.gi", + "pkg/crisp/lib/solveeq.gi", + "pkg/crisp/lib/compl.gi", + "pkg/crisp/lib/radical.gi", + "pkg/crisp/lib/residual.gi", + "pkg/crisp/lib/util.gi", + "pkg/crisp/lib/samples.gi", + "pkg/crisp/lib/socle.gi", + "pkg/factint/init.g", + "pkg/factint/lib/factint.gd", + "pkg/factint/read.g", + "pkg/factint/tables/3k2k.g", + "pkg/factint/tables/akbk.g", + "pkg/factint/tables/factorial.g", + "pkg/factint/tables/fibo.g", + "pkg/factint/tables/primorial.g", + "pkg/factint/lib/general.gi", + "pkg/factint/lib/pminus1.gi", + "pkg/factint/lib/pplus1.gi", + "pkg/factint/lib/ecm.gi", + "pkg/factint/lib/cfrac.gi", + "pkg/factint/lib/mpqs.gi", + "pkg/forms/init.g", + "pkg/forms/lib/forms.gd", + "pkg/forms/lib/recognition.gd", + "pkg/forms/lib/conformal.gd", + "pkg/forms/read.g", + "pkg/forms/lib/forms.gi", + "pkg/forms/lib/recognition.gi", + "pkg/forms/lib/classic.gi", + "pkg/forms/lib/recognition_new.gi", + "pkg/forms/lib/conformal.gi", + "pkg/orb/init.g", + "pkg/orb/gap/homwdata.gd", + "pkg/orb/gap/avltree.gd", + "pkg/orb/gap/hash.gd", + "pkg/orb/gap/cache.gd", + "pkg/orb/gap/orbits.gd", + "pkg/orb/gap/search.gd", + "pkg/orb/gap/bysuborbit.gd", + "pkg/orb/read.g", + "pkg/orb/gap/homwdata.gi", + "pkg/orb/gap/avltree.gi", + "pkg/orb/gap/hash.gi", + "pkg/orb/gap/cache.gi", + "pkg/orb/gap/orbits.gi", + "pkg/orb/gap/search.gi", + "pkg/orb/gap/bysuborbit.gi", + "pkg/utils/init.g", + "pkg/utils/lib/start.gd", + "pkg/utils/lib/files.gd", + "pkg/utils/lib/groups.gd", + "pkg/utils/lib/iterator.gd", + "pkg/utils/lib/latex.gd", + "pkg/utils/lib/lcset.gd", + "pkg/utils/lib/lists.gd", + "pkg/utils/lib/magma.gd", + "pkg/utils/lib/maps.gd", + "pkg/utils/lib/matrix.gd", + "pkg/utils/lib/number.gd", + "pkg/utils/lib/print.gd", + "pkg/utils/lib/record.gd", + "pkg/utils/lib/string.gd", + "pkg/utils/lib/gslp.gd", + "pkg/utils/lib/download.gd", + "pkg/utils/read.g", + "pkg/utils/lib/files.gi", + "pkg/utils/lib/groups.gi", + "pkg/utils/lib/iterator.gi", + "pkg/utils/lib/latex.gi", + "pkg/utils/lib/lcset.gi", + "pkg/utils/lib/lists.gi", + "pkg/utils/lib/magma.gi", + "pkg/utils/lib/maps.gi", + "pkg/utils/lib/matrix.gi", + "pkg/utils/lib/number.gi", + "pkg/utils/lib/print.gi", + "pkg/utils/lib/record.gi", + "pkg/utils/lib/string.gi", + "pkg/utils/lib/gslp.gi", + "pkg/utils/lib/download.gi", + "pkg/genss/init.g", + "pkg/genss/gap/genss.gd", + "pkg/genss/gap/setwise.gd", + "pkg/genss/read.g", + "pkg/genss/gap/genss.gi", + "pkg/genss/gap/setwise.gi", + "pkg/atlasrep/init.g", + "pkg/atlasrep/gap/userpref.g", + "pkg/atlasrep/gap/bbox.gd", + "pkg/atlasrep/gap/access.gd", + "pkg/atlasrep/gap/scanmtx.gd", + "pkg/atlasrep/gap/scanmtx.gi", + "pkg/atlasrep/gap/types.gd", + "pkg/atlasrep/gap/interfac.gd", + "pkg/atlasrep/gap/mindeg.gd", + "pkg/atlasrep/gap/utils.gd", + "pkg/ctbllib/init.g", + "pkg/ctbllib/gap4/ctadmin.gd", + "pkg/ctbllib/gap4/construc.gd", + "pkg/ctbllib/gap4/ctblothe.gd", + "pkg/ctbllib/dlnames/dlnames.gd", + "pkg/ctbllib/gap4/obsolete.gd", + "pkg/ctbllib/gap4/brdbattrX.gd", + "pkg/ctbllib/gap4/brdbattrX.gi", + "pkg/recog/init.g", + "pkg/recog/gap/base/hack.g", + "pkg/recog/gap/base/methods.gd", + "pkg/recog/gap/base/methsel.gd", + "pkg/recog/gap/base/recognition.gd", + "pkg/recog/gap/base/kernel.gd", + "pkg/recog/gap/base/projective.gd", + "pkg/recog/gap/matrix/ppd.gd", + "pkg/recog/gap/matrix/classical.gd", + "pkg/recog/gap/projective/almostsimple.gd", + "pkg/recog/gap/projective/findnormal.gd", + "pkg/recog/gap/projective/AnSnOnFDPM.gd", + "pkg/spinsym/init.g", + "pkg/spinsym/gap/mtx.gd", + "pkg/spinsym/gap/fus.gd", + "pkg/spinsym/gap/young.gd", + "pkg/standardff/init.g", + "pkg/standardff/lib/Util.gd", + "pkg/standardff/lib/IsIrred.gd", + "pkg/standardff/lib/StandardFF.gd", + "pkg/standardff/lib/StandardCyc.gd", + "pkg/tomlib/init.g", + "pkg/tomlib/gap/tmadmin.tmd", + "pkg/tomlib/gap/stdgen.gd", + "pkg/atlasrep/read.g", + "pkg/atlasrep/gap/bbox.gi", + "pkg/atlasrep/gap/access.gi", + "pkg/atlasrep/gap/types.gi", + "pkg/atlasrep/gap/interfac.gi", + "pkg/atlasrep/gap/mindeg.gi", + "pkg/atlasrep/gap/utlmrkup.g", + "pkg/atlasrep/gap/utils.gi", + "pkg/atlasrep/gap/test.g", + "pkg/atlasrep/gap/json.g", + "pkg/atlasrep/gap/obsolete.gd", + "pkg/atlasrep/gap/obsolete.gi", + "pkg/ctbllib/read.g", + "pkg/ctbllib/gap4/ctadmin.gi", + "pkg/ctbllib/gap4/ctprimar.g", + "pkg/ctbllib/data/firstnames.json", + "pkg/ctbllib/data/othernames.json", + "pkg/ctbllib/data/fusionsources.json", + "pkg/ctbllib/data/extinfo.json", + "pkg/ctbllib/data/ctgeneri.tbl", + "pkg/ctbllib/data/version", + "pkg/ctbllib/data/namerepl.json", + "pkg/ctbllib/gap4/construc.gi", + "pkg/ctbllib/gap4/ctblothe.gi", + "pkg/ctbllib/gap4/test.g", + "pkg/ctbllib/dlnames/dlnames.gi", + "pkg/ctbllib/gap4/ctbltoct.g", + "pkg/ctbllib/gap4/ctdbattr.g", + "pkg/ctbllib/gap4/od.g", + "pkg/ctbllib/data/odresults.json", + "pkg/ctbllib/gap4/atlasstr.g", + "pkg/ctbllib/gap4/atlasirr.g", + "pkg/recog/read.g", + "pkg/recog/gap/base/methods.gi", + "pkg/recog/gap/base/methsel.gi", + "pkg/recog/gap/base/recognition.gi", + "pkg/recog/gap/base/kernel.gi", + "pkg/recog/gap/base/projective.gi", + "pkg/recog/gap/utils.gi", + "pkg/recog/gap/generic/TrivialGroup.gi", + "pkg/recog/gap/generic/FewGensAbelian.gi", + "pkg/recog/gap/generic/KnownNilpotent.gi", + "pkg/recog/gap/perm/giant.gi", + "pkg/recog/gap/perm/largebase.gi", + "pkg/recog/gap/SnAnBB.gi", + "pkg/recog/gap/generic/SnAnUnknownDegree.gi", + "pkg/recog/gap/matrix/matimpr.gi", + "pkg/recog/gap/matrix/blocks.gi", + "pkg/recog/gap/matrix/ppd.gi", + "pkg/recog/gap/matrix/classical.gi", + "pkg/recog/gap/matrix/slconstr.gi", + "pkg/recog/gap/projective/findnormal.gi", + "pkg/recog/gap/projective/c6.gi", + "pkg/recog/gap/projective/tensor.gi", + "pkg/recog/gap/projective/c3c5.gi", + "pkg/recog/gap/projective/d247.gi", + "pkg/recog/gap/projective/almostsimple/threeelorders.gi", + "pkg/recog/gap/projective/almostsimple.gi", + "pkg/recog/gap/projective/almostsimple/lietype.gi", + "pkg/recog/gap/projective/almostsimple/hints.gi", + "pkg/recog/gap/projective/classicalnatural.gi", + "pkg/recog/gap/projective/sl2_natural.gi", + "pkg/recog/gap/projective/sl.gi", + "pkg/recog/gap/projective/AnSnOnFDPM.gi", + "pkg/recog/gap/perm.gi", + "pkg/recog/gap/matrix.gi", + "pkg/recog/gap/projective.gi", + "pkg/spinsym/read.g", + "pkg/spinsym/gap/mtx.gi", + "pkg/spinsym/gap/fus.gi", + "pkg/spinsym/gap/young.gi", + "pkg/standardff/read.g", + "pkg/standardff/lib/Util.gi", + "pkg/standardff/lib/IsIrred.gi", + "pkg/standardff/lib/StandardFF.gi", + "pkg/standardff/lib/StandardCyc.gi", + "pkg/standardff/lib/CANFACT.g", + "pkg/standardff/lib/TestFuncs.g", + "pkg/tomlib/read.g", + "pkg/tomlib/gap/tmstdrd.tom", + "pkg/tomlib/gap/tmadmin.tmi", + "pkg/tomlib/gap/stdgen.gi", + "pkg/atlasrep/gap/ctbllib_only.g", + "pkg/ctbllib/gap4/atlasrep_only.g", + "pkg/ctbllib/gap4/tomlib_only.g", + "pkg/ctbllib/data/tom_tbl.json", + "pkg/ctbllib/gap4/spinsym_only.g", + "pkg/ctbllib/data/grp_atlas.json", + "pkg/ctbllib/data/attr_nccl.json", + "pkg/ctbllib/data/grp_small.json", + "pkg/ctbllib/data/grp_tom.json", + "pkg/ctbllib/data/grp_trans.json", + "pkg/ctbllib/data/grp_prim.json", + "pkg/ctbllib/data/grp_perf.json", + "pkg/fga/init.g", + "pkg/fga/lib/util.gd", + "pkg/fga/lib/Iterated.gd", + "pkg/fga/lib/Autom.gd", + "pkg/fga/lib/FreeGrps.gd", + "pkg/fga/lib/ReprAct.gd", + "pkg/fga/lib/Normal.gd", + "pkg/fga/lib/ExtAutom.gd", + "pkg/fga/lib/Hom.gd", + "pkg/fga/lib/AutGrp.gd", + "pkg/fga/lib/Intsect.gd", + "pkg/fga/lib/Whitehd.gd", + "pkg/fga/read.g", + "pkg/fga/lib/util.gi", + "pkg/fga/lib/Iterated.gi", + "pkg/fga/lib/Autom.gi", + "pkg/fga/lib/FreeGrps.gi", + "pkg/fga/lib/ReprAct.gi", + "pkg/fga/lib/Normal.gi", + "pkg/fga/lib/Central.gi", + "pkg/fga/lib/Index.gi", + "pkg/fga/lib/ExtAutom.gi", + "pkg/fga/lib/Hom.gi", + "pkg/fga/lib/AutGrp.gi", + "pkg/fga/lib/Intsect.gi", + "pkg/fga/lib/ReprActT.gi", + "pkg/fga/lib/Whitehd.gi", + "pkg/irredsol/init.g", + "pkg/irredsol/lib/util.g", + "pkg/irredsol/lib/util.gd", + "pkg/irredsol/lib/matmeths.gd", + "pkg/irredsol/lib/loading.gd", + "pkg/irredsol/lib/loadfp.gd", + "pkg/irredsol/lib/access.gd", + "pkg/irredsol/lib/iterators.gd", + "pkg/irredsol/lib/recognize.gd", + "pkg/irredsol/lib/primitive.gd", + "pkg/irredsol/lib/recognizeprim.gd", + "pkg/irredsol/lib/obsolete.gd", + "pkg/irredsol/read.g", + "pkg/irredsol/lib/matmeths.gi", + "pkg/irredsol/lib/loading.gi", + "pkg/irredsol/lib/loadfp.gi", + "pkg/irredsol/lib/access.gi", + "pkg/irredsol/lib/iterators.gi", + "pkg/irredsol/lib/recognize.gi", + "pkg/irredsol/lib/primitive.gi", + "pkg/irredsol/lib/recognizeprim.gi", + "pkg/irredsol/lib/util.gi", + "pkg/irredsol/lib/obsolete.gi", + "pkg/sophus/init.g", + "pkg/sophus/gap/sophus.gd", + "pkg/sophus/read.g", + "pkg/sophus/gap/general.gi", + "pkg/sophus/gap/lienp.gi", + "pkg/sophus/gap/liesct.gi", + "pkg/sophus/gap/liecover.gi", + "pkg/sophus/gap/nicestab.gi", + "pkg/sophus/gap/lieautoops.gi", + "pkg/sophus/gap/initauts.gi", + "pkg/sophus/gap/lieautgrp.gi", + "pkg/sophus/gap/allowable.gi", + "pkg/sophus/gap/descendant.gi", + "pkg/sophus/gap/lieisom.gi", + "pkg/sophus/gap/io.gi", + "pkg/laguna/init.g", + "pkg/laguna/lib/laguna.gd", + "pkg/laguna/lib/laguna.g", + "pkg/laguna/read.g", + "pkg/laguna/lib/laguna.gi", + "pkg/autodoc/init.g", + "pkg/autodoc/gap/DocumentationTree.gd", + "pkg/autodoc/gap/Parser.gd", + "pkg/autodoc/gap/AutoDocMainFunction.gd", + "pkg/autodoc/gap/ToolFunctions.gd", + "pkg/autodoc/gap/Magic.gd", + "pkg/autodoc/gap/Markdown.gd", + "pkg/autodoc/read.g", + "pkg/autodoc/gap/ToolFunctions.gi", + "pkg/autodoc/gap/DocumentationTree.gi", + "pkg/autodoc/gap/Parser.gi", + "pkg/autodoc/gap/AutoDocMainFunction.gi", + "pkg/autodoc/gap/Magic.gi", + "pkg/autodoc/gap/Markdown.gi", + "pkg/packagemanager/init.g", + "pkg/packagemanager/gap/PackageManager.gd", + "pkg/packagemanager/gap/archive.gd", + "pkg/packagemanager/gap/compile.gd", + "pkg/packagemanager/gap/directories.gd", + "pkg/packagemanager/gap/distro.gd", + "pkg/packagemanager/gap/doc.gd", + "pkg/packagemanager/gap/download.gd", + "pkg/packagemanager/gap/git.gd", + "pkg/packagemanager/gap/hg.gd", + "pkg/packagemanager/gap/interactive.gd", + "pkg/packagemanager/gap/packageinfo.gd", + "pkg/packagemanager/read.g", + "pkg/packagemanager/gap/PackageManager.gi", + "pkg/packagemanager/gap/archive.gi", + "pkg/packagemanager/gap/compile.gi", + "pkg/packagemanager/gap/directories.gi", + "pkg/packagemanager/gap/distro.gi", + "pkg/packagemanager/gap/doc.gi", + "pkg/packagemanager/gap/download.gi", + "pkg/packagemanager/gap/git.gi", + "pkg/packagemanager/gap/hg.gi", + "pkg/packagemanager/gap/interactive.gi", + "pkg/packagemanager/gap/packageinfo.gi", + "pkg/radiroot/init.g", + "pkg/radiroot/lib/Radicals.gd", + "pkg/radiroot/lib/SplittField.gd", + "pkg/radiroot/lib/Manipulations.gd", + "pkg/radiroot/lib/Strings.gd", + "pkg/radiroot/lib/Maple.gd", + "pkg/radiroot/read.g", + "pkg/radiroot/lib/Radicals.gi", + "pkg/radiroot/lib/SplittField.gi", + "pkg/radiroot/lib/Manipulations.gi", + "pkg/radiroot/lib/Strings.gi", + "pkg/radiroot/lib/Maple.gi", + "pkg/aclib/init.g", + "pkg/aclib/gap/groups.gd", + "pkg/cryst/init.g", + "pkg/cryst/gap/common.gd", + "pkg/cryst/gap/cryst.gd", + "pkg/cryst/gap/hom.gd", + "pkg/cryst/gap/wyckoff.gd", + "pkg/cryst/gap/zass.gd", + "pkg/cryst/gap/max.gd", + "pkg/cryst/gap/color.gd", + "pkg/cryst/gap/equiv.gd", + "pkg/cryst/grp/spacegrp.gd", + "pkg/crystcat/init.g", + "pkg/crystcat/lib/crystcat.gd", + "pkg/polenta/init.g", + "pkg/polenta/lib/finite.gd", + "pkg/polenta/lib/info.gd", + "pkg/polenta/lib/basic.gd", + "pkg/polenta/exam/test.gd", + "pkg/polenta/lib/cpcs.gd", + "pkg/polenta/lib/present.gd", + "pkg/polenta/lib/solvable.gd", + "pkg/polenta/lib/series.gd", + "pkg/polenta/lib/subgroups.gd", + "pkg/polenta/lib/ispolyz.gd", + "pkg/aclib/read.g", + "pkg/aclib/gap/matgrp3.gi", + "pkg/aclib/gap/matgrp4.gi", + "pkg/aclib/gap/matgrp.gi", + "pkg/aclib/gap/pcpgrp3.gi", + "pkg/aclib/gap/pcpgrp4.gi", + "pkg/aclib/gap/pcpgrp.gi", + "pkg/aclib/gap/betti.gi", + "pkg/aclib/gap/union.gi", + "pkg/aclib/gap/extend.gi", + "pkg/aclib/gap/crystgrp.gi", + "pkg/cryst/read.g", + "pkg/cryst/gap/common.gi", + "pkg/cryst/gap/hom.gi", + "pkg/cryst/gap/cryst.gi", + "pkg/cryst/gap/cryst2.gi", + "pkg/cryst/gap/fpgrp.gi", + "pkg/cryst/gap/zass.gi", + "pkg/cryst/gap/max.gi", + "pkg/cryst/gap/wyckoff.gi", + "pkg/cryst/gap/color.gi", + "pkg/cryst/gap/noxgap.gi", + "pkg/cryst/gap/pcpgrp.gi", + "pkg/cryst/gap/orbstab.gi", + "pkg/cryst/gap/equiv.gi", + "pkg/cryst/grp/spacegrp.grp", + "pkg/cryst/grp/spacegrp.gi", + "pkg/crystcat/read.g", + "pkg/crystcat/grp/crystcat.grp", + "pkg/crystcat/lib/crystcat.gi", + "pkg/crystcat/lib/normalizer.gi", + "pkg/polenta/read.g", + "pkg/polenta/lib/finite.gi", + "pkg/polenta/lib/basic.gi", + "pkg/polenta/lib/unipo.gi", + "pkg/polenta/lib/series.gi", + "pkg/polenta/lib/semi.gi", + "pkg/polenta/lib/ispoly.gi", + "pkg/polenta/lib/cpcs.gi", + "pkg/polenta/lib/present.gi", + "pkg/polenta/lib/isom.gi", + "pkg/polenta/lib/solvable.gi", + "pkg/polenta/exam/exam.gi", + "pkg/polenta/exam/test.gi", + "pkg/polenta/lib/subgroups.gi", + "pkg/polenta/lib/ispolyz.gi", + "pkg/resclasses/init.g", + "pkg/resclasses/lib/general.gd", + "pkg/resclasses/lib/z_pi.gd", + "pkg/resclasses/lib/resclass.gd", + "pkg/resclasses/lib/fixedrep.gd", + "pkg/resclasses/read.g", + "pkg/resclasses/lib/general.gi", + "pkg/resclasses/lib/resclaux.g", + "pkg/resclasses/lib/z_pi.gi", + "pkg/resclasses/lib/resclass.gi", + "pkg/resclasses/lib/fixedrep.gi", + "lib/obsolete.gi", + "pkg/4ti2interface/doc/manual.six", + "pkg/ace/doc/manual.six", + "pkg/aclib/doc/manual.six", + "pkg/agt/doc/manual.six", + "pkg/alco/doc/manual.six", + "pkg/alnuth/doc/manual.six", + "pkg/anupq/doc/manual.six", + "pkg/atlasrep/doc/manual.six", + "pkg/autodoc/doc/manual.six", + "pkg/automata/doc/manual.six", + "pkg/automgrp/doc/manual.six", + "pkg/autpgrp/doc/manual.six", + "pkg/browse/doc/manual.six", + "pkg/cap/doc/manual.six", + "pkg/caratinterface/doc/manual.six", + "pkg/cddinterface/doc/manual.six", + "pkg/circle/doc/manual.six", + "pkg/classicalmaximals/doc/manual.six", + "pkg/classicpres/doc/manual.six", + "pkg/cohomolo/doc/manual.six", + "pkg/congruence/doc/manual.six", + "pkg/corefreesub/doc/manual.six", + "pkg/corelg/doc/manual.six", + "pkg/crime/doc/manual.six", + "pkg/crisp/doc/manual.six", + "pkg/crypting/doc/manual.six", + "pkg/cryst/doc/manual.six", + "pkg/crystcat/doc/manual.six", + "pkg/ctbllib/doc/manual.six", + "pkg/ctbllib/doc2/manual.six", + "pkg/cubefree/doc/manual.six", + "pkg/curlinterface/doc/manual.six", + "pkg/cvec/doc/manual.six", + "pkg/datastructures/doc/manual.six", + "pkg/deepthought/doc/manual.six", + "pkg/design/doc/manual.six", + "pkg/difsets/doc/manual.six", + "pkg/digraphs/doc/manual.six", + "pkg/edim/doc/manual.six", + "pkg/example/doc/manual.six", + "pkg/examplesforhomalg/doc/manual.six", + "pkg/factint/doc/manual.six", + "pkg/ferret/doc/manual.six", + "pkg/fga/doc/manual.six", + "pkg/fining/doc/manual.six", + "pkg/float/doc/manual.six", + "pkg/format/doc/manual.six", + "pkg/forms/doc/manual.six", + "pkg/fplsa/doc/manual.six", + "pkg/fr/doc/manual.six", + "pkg/francy/doc/manual.six", + "pkg/fwtree/doc/manual.six", + "pkg/gapdoc/doc/manual.six", + "pkg/gapdoc/example/manual.six", + "pkg/gauss/doc/manual.six", + "pkg/gaussforhomalg/doc/manual.six", + "pkg/gbnp/doc/manual.six", + "pkg/generalizedmorphismsforcap/doc/manual.six", + "pkg/genss/doc/manual.six", + "pkg/gradedmodules/doc/manual.six", + "pkg/gradedringforhomalg/doc/manual.six", + "pkg/grape/doc/manual.six", + "pkg/groupoids/doc/manual.six", + "pkg/grpconst/doc/manual.six", + "pkg/guarana/doc/manual.six", + "pkg/guava/doc/manual.six", + "pkg/hap/doc/manual.six", + "pkg/hapcryst/doc/manual.six", + "pkg/hecke/doc/manual.six", + "pkg/help/doc/manual.six", + "pkg/homalg/doc/manual.six", + "pkg/homalgtocas/doc/manual.six", + "pkg/ibnp/doc/manual.six", + "pkg/idrel/doc/manual.six", + "pkg/images/doc/manual.six", + "pkg/inducereduce/doc/manual.six", + "pkg/intpic/doc/manual.six", + "pkg/io/doc/manual.six", + "pkg/io_forhomalg/doc/manual.six", + "pkg/irredsol/doc/manual.six", + "pkg/itc/doc/manual.six", + "pkg/json/doc/manual.six", + "pkg/jupyterkernel/doc/manual.six", + "pkg/jupyterviz/doc/manual.six", + "pkg/kan/doc/manual.six", + "pkg/kbmag/doc/manual.six", + "pkg/laguna/doc/manual.six", + "pkg/liealgdb/doc/manual.six", + "pkg/liepring/doc/manual.six", + "pkg/liering/doc/manual.six", + "pkg/linearalgebraforcap/doc/manual.six", + "pkg/lins/doc/manual.six", + "pkg/localizeringforhomalg/doc/manual.six", + "pkg/localnr/doc/manual.six", + "pkg/loops/doc/manual.six", + "pkg/lpres/doc/manual.six", + "pkg/majoranaalgebras/doc/manual.six", + "pkg/mapclass/doc/manual.six", + "pkg/matgrp/doc/manual.six", + "pkg/matricesforhomalg/doc/manual.six", + "pkg/modisom/doc/manual.six", + "pkg/modulargroup/doc/manual.six", + "pkg/modulepresentationsforcap/doc/manual.six", + "pkg/modules/doc/manual.six", + "pkg/monoidalcategories/doc/manual.six", + "pkg/nconvex/doc/manual.six", + "pkg/nilmat/doc/manual.six", + "pkg/nock/doc/manual.six", + "pkg/nofoma/doc/manual.six", + "pkg/normalizinterface/doc/manual.six", + "pkg/nq/doc/manual.six", + "pkg/numericalsgps/doc/manual.six", + "pkg/openmath/doc/manual.six", + "pkg/orb/doc/manual.six", + "pkg/origami/doc/manual.six", + "pkg/packagemaker/doc/manual.six", + "pkg/packagemanager/doc/manual.six", + "pkg/patternclass/doc/manual.six", + "pkg/permut/doc/manual.six", + "pkg/polenta/doc/manual.six", + "pkg/polycyclic/doc/manual.six", + "pkg/polymaking/doc/manual.six", + "pkg/primgrp/doc/manual.six", + "pkg/profiling/doc/manual.six", + "pkg/qdistrnd/doc/manual.six", + "pkg/qpa/doc/manual.six", + "pkg/quagroup/doc/manual.six", + "pkg/radiroot/doc/manual.six", + "pkg/rcwa/doc/manual.six", + "pkg/rds/doc/manual.six", + "pkg/recog/doc/manual.six", + "pkg/repndecomp/doc/manual.six", + "pkg/repsn/doc/manual.six", + "pkg/resclasses/doc/manual.six", + "pkg/ringsforhomalg/doc/manual.six", + "pkg/sco/doc/manual.six", + "pkg/scscp/doc/manual.six", + "pkg/semigroups/doc/manual.six", + "pkg/sglppow/doc/manual.six", + "pkg/sgpviz/doc/manual.six", + "pkg/simpcomp/doc/manual.six", + "pkg/singular/doc/manual.six", + "pkg/sl2reps/doc/manual.six", + "pkg/sla/doc/manual.six", + "pkg/smallantimagmas/doc/manual.six", + "pkg/smallclassnr/doc/manual.six", + "pkg/smallgrp/doc/manual.six", + "pkg/smallsemi/doc/manual.six", + "pkg/sonata/doc/ref/manual.six", + "pkg/sonata/doc/tut/manual.six", + "pkg/sophus/doc/manual.six", + "pkg/sotgrps/doc/manual.six", + "pkg/spinsym/doc/manual.six", + "pkg/standardff/doc/manual.six", + "pkg/symbcompcc/doc/manual.six", + "pkg/thelma/doc/manual.six", + "pkg/tomlib/doc/manual.six", + "pkg/toolsforhomalg/doc/manual.six", + "pkg/toric/doc/manual.six", + "pkg/transgrp/doc/manual.six", + "pkg/twistedconjugacy/doc/manual.six", + "pkg/typeset/doc/manual.six", + "pkg/ugaly/doc/manual.six", + "pkg/unipot/doc/manual.six", + "pkg/unitlib/doc/manual.six", + "pkg/utils/doc/manual.six", + "pkg/uuid/doc/manual.six", + "pkg/walrus/doc/manual.six", + "pkg/wedderga/doc/manual.six", + "pkg/wpe/doc/manual.six", + "pkg/xgap/doc/manual.six", + "pkg/xmod/doc/manual.six", + "pkg/xmodalg/doc/manual.six", + "pkg/yangbaxter/doc/manual.six", + "pkg/zeromqinterface/doc/manual.six" +] diff --git a/etc/emscripten/web-template/gap-fs.js b/etc/emscripten/web-template/gap-fs.js index f3a1467d42..ca8ea4f23d 100644 --- a/etc/emscripten/web-template/gap-fs.js +++ b/etc/emscripten/web-template/gap-fs.js @@ -1,3 +1,29 @@ +// Instrument fetch and XMLHttpRequest so the page can collect the list of +// URLs the worker actually requests, for rebuilding startup_manifest.json +// without scraping the browser network panel. Each unique URL is posted +// to the main thread as { type: "gap-fetched", url: ... }. +(function instrumentFetches() { + const seen = new Set(); + const report = (raw) => { + if (typeof raw !== "string") return; + if (seen.has(raw)) return; + seen.add(raw); + self.postMessage({ type: "gap-fetched", url: raw }); + }; + + const origFetch = self.fetch; + self.fetch = function(input, init) { + report(typeof input === "string" ? input : input && input.url); + return origFetch.apply(this, arguments); + }; + + const origOpen = XMLHttpRequest.prototype.open; + XMLHttpRequest.prototype.open = function(method, url) { + report(url); + return origOpen.apply(this, arguments); + }; +})(); + self.Module = self.Module || {}; self.Module.preRun = self.Module.preRun || []; @@ -43,8 +69,12 @@ self.Module.preRun.push(function() { if (p.startsWith('/')) p = p.substring(1); startupSet.add(p); }); + } else { + console.info("startup_manifest.json not present; falling back to fully lazy loading"); } - } catch (e) {} + } catch (e) { + console.warn("Failed to load startup_manifest.json:", e); + } var fetchPromises = fileList.map(async function(appPath) { var fetchRelativePath = appPath.split('/').map(encodeURIComponent).join('/'); @@ -58,16 +88,15 @@ self.Module.preRun.push(function() { FS.stat(idbfsPath); FS.writeFile(finalAppPath, FS.readFile(idbfsPath)); } catch (e) { - try { - const response = await fetch(fetchPath); - if (response.ok) { - const buffer = await response.arrayBuffer(); - const data = new Uint8Array(buffer); - FS.writeFile(finalAppPath, data); - FS.writeFile(idbfsPath, data); - needsSave = true; - } - } catch (fetchErr) {} + const response = await fetch(fetchPath); + if (!response.ok) { + throw new Error("Failed to fetch startup file " + fetchPath + ": " + response.status); + } + const buffer = await response.arrayBuffer(); + const data = new Uint8Array(buffer); + FS.writeFile(finalAppPath, data); + FS.writeFile(idbfsPath, data); + needsSave = true; } } else { var parts = appPath.split('/'); diff --git a/etc/emscripten/web-template/index.html b/etc/emscripten/web-template/index.html index b51df45fb8..d5f1bec759 100755 --- a/etc/emscripten/web-template/index.html +++ b/etc/emscripten/web-template/index.html @@ -1,22 +1,185 @@ - + + - gap-wasm + + + GAP in the browser + -
+
+

GAP in the browser

+

+ A WebAssembly build of GAP + running entirely in your browser — useful for trying things out + without installing. Not all packages work, working memory is + capped, and performance is reduced compared to a native build. + For real work, install GAP from + www.gap-system.org. +

+
+ +
+ What is this? · Licensing +

+ GAP is a system for + computational discrete algebra, with particular emphasis on + computational group theory. This page is a self-contained + WebAssembly build, served as a static site and run inside a + Web Worker; you interact with it through an + xterm-pty + terminal in the page below. +

+

+ To get started, try 1+1;, + Factorial(20);, or SymmetricGroup(5);. + The full GAP + manuals apply, with two caveats: some packages won't load + (anything that needs a native compiler or system library), and + anything that wants the local filesystem won't work. +

+

+ Files downloaded on first visit are cached in your browser's + IndexedDB, so subsequent visits start much faster. Clear the + site data to reset the cache. +

+

+ GAP is free software, distributed under the + GNU General Public License (version 2 or + later). See the copyright notice for + the full statement. +

+
+ +
+ Loading GAP… The first visit downloads several tens of megabytes; + subsequent visits are cached in your browser and load much faster. +
+ +
+ This page needs SharedArrayBuffer, which is only + available when the page is served with the headers + Cross-Origin-Opener-Policy: same-origin and + Cross-Origin-Embedder-Policy: require-corp. The + bundled service worker handles this on hosts where you can't set + headers (e.g. GitHub Pages); for local hosting use + etc/emscripten/serve.py. +
+ +
+
+
+ + + diff --git a/src/gasman.c b/src/gasman.c index 6712ebec79..7a616d6eb6 100644 --- a/src/gasman.c +++ b/src/gasman.c @@ -129,7 +129,7 @@ #include #include -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ #include #endif @@ -1957,7 +1957,7 @@ static NOINLINE void GenStackFuncBags(void) DisableMarkBagValidation = 1; #endif -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ emscripten_scan_stack(ScanRange); emscripten_scan_registers(ScanRange); // The standard scanning may not be required with From 9de742a8c0804aa45fbefa0f426caf05b5f27adb Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 1 Jun 2026 13:41:50 +0200 Subject: [PATCH 021/114] Update COPYRIGHT --- COPYRIGHT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/COPYRIGHT b/COPYRIGHT index 6a58d3bd37..b144b05166 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with GAP; if not, see . -Copyright (C) 1988-2025 by its authors, which include: +Copyright (C) 1988-2026 by its authors, which include: * Ákos Seress * Alex Wegner From cb25fa70967f9fc7390e50eb8ae64c3fbfbb0afe Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 1 Jun 2026 22:34:43 +0200 Subject: [PATCH 022/114] Fix RingGeneralMappingByImages for non-SCRing (#6418) A filter was computed but not used. The filter that was used instead always implied IsSCRingGeneralMappingByImagesDefaultRep which is too broad. As a result, inappropriate methods were applied to some ring homomorphisms. Also add an example for using RingByStructureConstants. --- lib/ringhom.gi | 7 +------ lib/ringsc.gd | 8 ++++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/ringhom.gi b/lib/ringhom.gi index 6377e0ceec..887a991704 100644 --- a/lib/ringhom.gi +++ b/lib/ringhom.gi @@ -52,12 +52,7 @@ function( S, R, gens, imgs ) fi; # Make the general mapping. - map:= Objectify( TypeOfDefaultGeneralMapping( S, R, - IsSPGeneralMapping - and IsRingGeneralMapping - and IsSCRingGeneralMappingByImagesDefaultRep ), - rec( - ) ); + map:= Objectify( TypeOfDefaultGeneralMapping( S, R, filter ), rec( ) ); SetMappingGeneratorsImages(map,[Immutable(gens),Immutable(imgs)]); # return the general mapping diff --git a/lib/ringsc.gd b/lib/ringsc.gd index bd2116bcd7..9871317d71 100644 --- a/lib/ringsc.gd +++ b/lib/ringsc.gd @@ -47,6 +47,14 @@ DeclareSynonym("IsSubringSCRing",IsRing and IsSCRingObjCollection); ## it can be either a string name ## (then name1, name2 etc. are chosen) ## or a list of strings which are then chosen. +## T:=EmptySCTable( 1, 0 );; +## gap> SetEntrySCTable( T, 1, 1, [ 1, 1 ] ); +## gap> R:=RingByStructureConstants([9], T); # Z/9Z +## +## gap> Elements(R); +## [ 0*r.1, r.1, 2*r.1, 3*r.1, 4*r.1, 5*r.1, 6*r.1, 7*r.1, -r.1 ] +## ]]> ##
## ## <#/GAPDoc> From ac1d8e95823dd3039ab3c6655f76e9e8e4833aa4 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 1 Jun 2026 22:41:56 +0200 Subject: [PATCH 023/114] Update CHANGES.md --- CHANGES.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 48c602ec6b..a2e9050afa 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # GAP - history of changes -## GAP 4.16.0 (May 2026) +## GAP 4.16.0 (June 2026) The following gives an overview of the changes compared to the previous release. This list is not complete, many more internal or minor changes @@ -91,6 +91,7 @@ affect some users directly. ### Fixed bugs that could lead to unexpected errors +- [#6418](https://github.com/gap-system/gap/pull/6418) Fix `RingGeneralMappingByImages` for non-SCRing - [#6196](https://github.com/gap-system/gap/pull/6196) Fix an inconsistency problem in `IsFinite` for matrix groups over cycl. fields. - [#6159](https://github.com/gap-system/gap/pull/6159) Fix a potential error message about data types when computing extensions @@ -116,10 +117,10 @@ affect some users directly. #### Updated packages redistributed with GAP -The GAP 4.16.0 distribution contains 172 packages, of which 68 have been +The GAP 4.16.0 distribution contains 172 packages, of which 69 have been updated since GAP 4.15.1. The full list of updated packages is given below: -- [**4ti2Interface**](https://homalg-project.github.io/pkg/4ti2Interface): 2024.11-01 -> 2025.12-01 +- [**4ti2Interface**](https://homalg-project.github.io/pkg/4ti2Interface): 2024.11-01 -> 2026.05-01 - [**Alnuth**](https://gap-packages.github.io/alnuth): 3.2.1 -> 4.0.0 - [**ANUPQ**](https://gap-packages.github.io/anupq/): 3.3.2 -> 3.3.3 - [**AtlasRep**](https://www.math.rwth-aachen.de/~Thomas.Breuer/atlasrep): 2.1.9 -> 2.1.11 @@ -137,6 +138,7 @@ updated since GAP 4.15.1. The full list of updated packages is given below: - [**Digraphs**](https://digraphs.github.io/Digraphs): 1.13.1 -> 1.14.0 - [**ExamplesForHomalg**](https://homalg-project.github.io/pkg/ExamplesForHomalg): 2023.10-01 -> 2025.12-01 - [**ferret**](https://gap-packages.github.io/ferret/): 1.0.15 -> 1.0.16 +- [**float**](https://gap-packages.github.io/float/): 1.0.9 -> 1.0.10 - [**FORMAT**](https://gap-packages.github.io/format/): 1.4.4 -> 1.4.5 - [**Forms**](https://gap-packages.github.io/forms): 1.2.13 -> 1.3.0 - [**FPLSA**](https://gap-packages.github.io/FPLSA): 1.2.7 -> 1.2.8 @@ -157,7 +159,7 @@ updated since GAP 4.15.1. The full list of updated packages is given below: - [**IO_ForHomalg**](https://homalg-project.github.io/pkg/IO_ForHomalg): 2023.02-04 -> 2025.12-01 - [**json**](https://gap-packages.github.io/json/): 2.2.3 -> 2.4.0 - [**LinearAlgebraForCAP**](https://homalg-project.github.io/pkg/LinearAlgebraForCAP): 2025.09-01 -> 2026.05-04 -- [**LocalizeRingForHomalg**](https://homalg-project.github.io/pkg/LocalizeRingForHomalg): 2023.10-01 -> 2026.04-01 +- [**LocalizeRingForHomalg**](https://homalg-project.github.io/pkg/LocalizeRingForHomalg): 2023.10-01 -> 2026.05-01 - [**lpres**](https://gap-packages.github.io/lpres): 1.1.1 -> 1.1.2 - [**matgrp**](https://www.math.colostate.edu/~hulpke/matgrp): 0.72 -> 0.73 - [**MatricesForHomalg**](https://homalg-project.github.io/pkg/MatricesForHomalg): 2025.09-01 -> 2026.04-01 @@ -174,7 +176,7 @@ updated since GAP 4.15.1. The full list of updated packages is given below: - [**qpa**](https://gap-packages.github.io/qpa): 1.35 -> 1.37 - [**RCWA**](https://gap-packages.github.io/rcwa/): 4.8.0 -> 4.9.0 - [**recog**](https://gap-packages.github.io/recog): 1.4.4 -> 1.5.1 -- [**RingsForHomalg**](https://homalg-project.github.io/pkg/RingsForHomalg): 2024.11-02 -> 2025.12-01 +- [**RingsForHomalg**](https://homalg-project.github.io/pkg/RingsForHomalg): 2024.11-02 -> 2026.05-01 - [**SCO**](https://homalg-project.github.io/pkg/SCO): 2023.08-01 -> 2025.12-01 - [**Semigroups**](https://semigroups.github.io/Semigroups): 5.5.4 -> 5.6.3 - [**singular**](https://gap-packages.github.io/singular/): 2025.08.26 -> 2026.05.05 From 9490b09e1c0dc2b5adb144126c6d693dfb8e7bde Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 2 Jun 2026 00:03:15 +0200 Subject: [PATCH 024/114] Normalize release archive permissions (#6420) Remove group and other write bits before creating release archives. Keep package contents readable while preserving and normalizing executable bits. Co-authored-by: Codex --- .github/workflows/release.yml | 2 +- Makefile.rules | 7 ++++-- dev/releases/make_archives.py | 11 +++++---- dev/releases/test_archive_utils.py | 39 ++++++++++++++++++++++++++++++ dev/releases/utils.py | 24 ++++++++++++++++++ 5 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 dev/releases/test_archive_utils.py diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 36867a212c..eb4ce3c91b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -57,7 +57,7 @@ jobs: # run: python -m mypy --disallow-untyped-calls --disallow-untyped-defs dev/releases/*.py - name: "Run tests" - run: cd dev/releases && python -m pytest test_release_notes.py + run: cd dev/releases && python -m pytest unix: name: "Create Unix archives and data" diff --git a/Makefile.rules b/Makefile.rules index ffe22eb1ba..e2512739ec 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -24,8 +24,11 @@ default: all ######################################################################## # Developer helper targets ######################################################################## -test_release_notes: - cd dev/releases && python3 -m pytest test_release_notes.py +test_release_scripts: + cd dev/releases && python3 -m pytest +.PHONY: test_release_scripts + +test_release_notes: test_release_scripts .PHONY: test_release_notes diff --git a/dev/releases/make_archives.py b/dev/releases/make_archives.py index 5b06f8e0f3..33fe219c1b 100755 --- a/dev/releases/make_archives.py +++ b/dev/releases/make_archives.py @@ -29,6 +29,7 @@ from utils import ( download_with_sha256, error, + normalize_archive_permissions, notice, patchfile, verify_command_available, @@ -211,14 +212,11 @@ def run_with_log(args: List[str], name: str, msg: Optional[str] = None) -> None: notice("Extracting package tarballs") with tarfile.open(tmpdir + "/" + all_packages_tarball) as tar: tar.extractall(path="pkg") - # for some reason pkg sometimes ends up with permission 0700 so - # we make sure to fix that here - subprocess.run(["chmod", "0755", "pkg"], check=True) - # ensure all files are at readable by everyone - subprocess.run(["chmod", "-R", "a+r", "."], check=True) with tarfile.open(tmpdir + "/" + req_packages_tarball) as tar: tar.extractall(path=tmpdir + "/" + req_packages) + notice("Normalizing permissions in required packages") + normalize_archive_permissions(tmpdir + "/" + req_packages) notice("Building GAP's manuals") run_with_log(["make", "doc"], "gapdoc", "building the manuals") @@ -278,6 +276,9 @@ def run_with_log(args: List[str], name: str, msg: Optional[str] = None) -> None: notice("Removing generated files we don't want to distribute") run_with_log(["make", "distclean"], "make-distclean", "make distclean") + notice("Normalizing permissions in GAP archive tree") + normalize_archive_permissions(".") + # Create an archive in the current directory with shutil.make_archive, and # record the filename of the new archive in . diff --git a/dev/releases/test_archive_utils.py b/dev/releases/test_archive_utils.py new file mode 100644 index 0000000000..ef05608a4a --- /dev/null +++ b/dev/releases/test_archive_utils.py @@ -0,0 +1,39 @@ +import os +import stat + +from utils import normalize_archive_permissions + + +def mode(path): + return stat.S_IMODE(os.stat(path).st_mode) + + +def test_normalize_archive_permissions_removes_group_and_other_write_bits(tmp_path): + package_dir = tmp_path / "pkg" + package_dir.mkdir() + private_dir = package_dir / "private" + private_dir.mkdir() + unreadable_dir = package_dir / "unreadable" + unreadable_dir.mkdir() + world_writable_file = package_dir / "data.g" + world_writable_file.write_text("data", encoding="utf-8") + executable_file = package_dir / "script.sh" + executable_file.write_text("#!/bin/sh\n", encoding="utf-8") + oddly_executable_file = package_dir / "odd.g" + oddly_executable_file.write_text("data", encoding="utf-8") + + os.chmod(package_dir, 0o777) + os.chmod(private_dir, 0o700) + os.chmod(unreadable_dir, 0o600) + os.chmod(world_writable_file, 0o666) + os.chmod(executable_file, 0o777) + os.chmod(oddly_executable_file, 0o654) + + normalize_archive_permissions(tmp_path) + + assert mode(package_dir) == 0o755 + assert mode(private_dir) == 0o755 + assert mode(unreadable_dir) == 0o755 + assert mode(world_writable_file) == 0o644 + assert mode(executable_file) == 0o755 + assert mode(oddly_executable_file) == 0o644 diff --git a/dev/releases/utils.py b/dev/releases/utils.py index e38c0ba72f..c14420f7c6 100644 --- a/dev/releases/utils.py +++ b/dev/releases/utils.py @@ -12,6 +12,7 @@ import os import re import shutil +import stat import subprocess import sys from typing import Iterator, NoReturn @@ -74,6 +75,29 @@ def working_directory(path: str) -> Iterator[None]: os.chdir(prev_cwd) +def normalize_archive_permissions(root: str) -> None: + """Apply the archive permission policy recursively below ``root``. + + This mirrors ``chmod -R g-w,o-w,g+r,o+r`` for regular files and also makes + directories searchable by group and others. File executable bits are + normalized from the owner's executable bit, so scripts remain executable + without making ordinary data files executable. Symlinks are left untouched. + """ + for dirpath, dirnames, filenames in os.walk(root): + for name in [dirpath, *dirnames, *filenames]: + path = os.path.join(dirpath, name) if name != dirpath else dirpath + if os.path.islink(path): + continue + mode = stat.S_IMODE(os.stat(path).st_mode) + mode |= stat.S_IRGRP | stat.S_IROTH + mode &= ~(stat.S_IWGRP | stat.S_IWOTH) + if os.path.isdir(path) or mode & stat.S_IXUSR: + mode |= stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH + else: + mode &= ~(stat.S_IXGRP | stat.S_IXOTH) + os.chmod(path, mode) + + # compute the sha256 checksum of a file def sha256file(path: str) -> str: h = hashlib.sha256() From 8ae5f61d6d6773e6f2ec4923fec5411674920334 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 5 Jun 2026 17:51:53 +0200 Subject: [PATCH 025/114] julia-gc: introduce DISABLE_STACK_SCAN (#6421) Useful for debugging, and future work on alternative GC integration. --- src/julia_gc.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/julia_gc.c b/src/julia_gc.c index 568b567b1e..f04d51e918 100644 --- a/src/julia_gc.c +++ b/src/julia_gc.c @@ -67,6 +67,8 @@ // should not be enabled by default. // #define VALIDATE_MARKING +// if DISABLE_STACK_SCAN is defined, all stack scanning is disabled +// #define DISABLE_STACK_SCAN // if USE_GAP_INSIDE_JULIA is defined, then some hacks which are needed // to make julia-inside-gap work are disabled. This is mainly for use in @@ -166,13 +168,15 @@ static jl_datatype_t * DatatypeGapObj; static jl_datatype_t * DatatypeSmallBag; static jl_datatype_t * DatatypeLargeBag; +#ifndef DISABLE_STACK_SCAN static jl_task_t * ScannedRootTask; +#endif static size_t MaxPoolObjSize; static int FullGC; static UInt StartTime, TotalTime; -#if !defined(USE_GAP_INSIDE_JULIA) +#if !defined(USE_GAP_INSIDE_JULIA) && !defined(DISABLE_STACK_SCAN) static Bag * GapStackBottom; static jl_task_t * RootTaskOfMainThread; #endif @@ -184,8 +188,10 @@ static TNumFreeFuncBags TabFreeFuncBags[NUM_TYPES]; // HACK: TabMarkFuncBags is accessed by MarkCopyingSubBags in src/objects.c TNumMarkFuncBags TabMarkFuncBags[NUM_TYPES]; +#ifndef DISABLE_STACK_SCAN static TaskInfoTree * TaskStacks; static pthread_mutex_t TaskStacksMutex; +#endif // // global bags @@ -325,6 +331,8 @@ void MarkJuliaWeakRef(void * p, void * ref) } +#ifndef DISABLE_STACK_SCAN + // Overview of conservative stack scanning // // A key aspect of conservative marking is that we need to determine whether a @@ -627,6 +635,8 @@ static void GapTaskScanner(jl_task_t * task, int root_task) } } +#endif // DISABLE_STACK_SCAN + // Julia callback static void PreGCHook(int full) { @@ -653,7 +663,9 @@ static void PreGCHook(int full) // Julia callback static void PostGCHook(int full) { +#ifndef DISABLE_STACK_SCAN ScannedRootTask = 0; +#endif TotalTime += SyTime() - StartTime; #ifdef COLLECT_MARK_CACHE_STATS /* printf("\n>>>Attempts: %ld\nHit rate: %lf\nCollision rate: %lf\n", @@ -758,6 +770,7 @@ void GAP_InitJuliaMemoryInterface(jl_module_t * module, jl_init(); #endif +#ifndef DISABLE_STACK_SCAN if (jl_n_gcthreads > 1) pthread_mutex_init(&TaskStacksMutex, NULL); TaskStacks = TaskInfoTreeMake(); @@ -766,6 +779,7 @@ void GAP_InitJuliaMemoryInterface(jl_module_t * module, // TLS and thus need to be installed after initialization. jl_gc_set_cb_root_scanner(GapRootScanner, 1); jl_gc_set_cb_task_scanner(GapTaskScanner, 1); +#endif jl_gc_set_cb_pre_gc(PreGCHook, 1); jl_gc_set_cb_post_gc(PostGCHook, 1); // jl_gc_enable(0); /// DEBUGGING @@ -816,7 +830,7 @@ void InitBags(UInt initial_size, Bag * stack_bottom) { TotalTime = 0; -#if !defined(USE_GAP_INSIDE_JULIA) +#if !defined(USE_GAP_INSIDE_JULIA) && !defined(DISABLE_STACK_SCAN) // initialize Julia memory interface. Note that this is only necessary // when we run standalone. In contrast, when GAP is loaded from GAP.jl // then GAP.jl invokes `GAP_InitJuliaMemoryInterface` at an appropriate From 2485080438691d962fcd15b341077c7b80a1fb39 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 6 Jun 2026 08:35:18 +0200 Subject: [PATCH 026/114] Miscellaneous kernel tweaks (#6422) * kernel: fix typo in src/gasman.c * CREATE_PTY_IOSTREAM: require args as plist * ExecuteProcess: require args as plist * kernel: change AUTO to require plain list --- lib/streams.gi | 3 +++ src/gasman.c | 4 ++-- src/gvars.c | 11 ++++++++--- src/iostream.c | 12 +++++++----- tst/testinstall/kernel/streams.tst | 2 +- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/lib/streams.gi b/lib/streams.gi index 5f0f44aa73..f105a1c635 100644 --- a/lib/streams.gi +++ b/lib/streams.gi @@ -1367,6 +1367,9 @@ InstallGlobalFunction( InputOutputLocalProcess, Error("Can't handle new rep for directories"); fi; dirname := cdir![1]; + if not IsPlistRep(argts) then + argts := PlainListCopy(argts); + fi; ptynum := CREATE_PTY_IOSTREAM( dirname, exec, argts); if ptynum = fail then return fail; diff --git a/src/gasman.c b/src/gasman.c index 7a616d6eb6..0575a384b7 100644 --- a/src/gasman.c +++ b/src/gasman.c @@ -2026,7 +2026,7 @@ static UInt CollectBags_Mark(UInt FullBags) // For old bags, we invoke the marking function for bags with the // given TNUM. // Young bags normally are never put onto the changed list, because - // CHANGED_BAGS ignores young bags. However, it can happen if we + // CHANGED_BAG ignores young bags. However, it can happen if we // resize an old bag and it needs to be moved as a result, or if we // swap the masterpointers of an old and a young bag. In that case, // we must be careful to not collect the young bag (which was old @@ -2566,7 +2566,7 @@ void CheckMasterPointers( void ) // we must make sure to mark the new bag2 as changed, too (and vice-versa). // // 2. Both bags are young. Then they typically will not be on the list of -// changed bags, as CHANGED_BAGS just skips them. +// changed bags, as CHANGED_BAG just skips them. // However, while CHANGED_BAG will never put a young bag on the list of // changed bags, young bags can still be put on the ChangedBags list in // step 3, so we need to do something similar as in step 1. diff --git a/src/gvars.c b/src/gvars.c index e705d8e885..5232cd2d21 100644 --- a/src/gvars.c +++ b/src/gvars.c @@ -832,19 +832,24 @@ static Obj FuncAUTO(Obj self, Obj args) UInt gvar; // one global variable UInt i; // loop variable + RequirePlainList(SELF_NAME, args); + RequireDenseList(SELF_NAME, args); + RequireArgumentCondition(SELF_NAME, args, LEN_PLIST(args) >= 2, + "must be a list of length at least 2"); + // get and check the function - func = ELM_LIST( args, 1 ); + func = ELM_PLIST( args, 1 ); RequireFunction(SELF_NAME, func); // get the argument - arg = ELM_LIST( args, 2 ); + arg = ELM_PLIST( args, 2 ); // make the list of function and argument list = NewPlistFromArgs(func, arg); // make the global variables automatic for ( i = 3; i <= LEN_LIST(args); i++ ) { - name = ELM_LIST( args, i ); + name = ELM_PLIST( args, i ); RequireStringRep(SELF_NAME, name); gvar = GVarName( CONST_CSTR_STRING(name) ); SET_ELM_GVAR_LIST( ValGVars, gvar, 0 ); diff --git a/src/iostream.c b/src/iostream.c index c108389724..3773f4b3a3 100644 --- a/src/iostream.c +++ b/src/iostream.c @@ -30,6 +30,7 @@ #include "io.h" #include "lists.h" #include "modules.h" +#include "plist.h" #include "stringobj.h" #include "sysenv.h" #include "sysfiles.h" @@ -858,13 +859,14 @@ static Obj FuncCREATE_PTY_IOSTREAM(Obj self, Obj dir, Obj prog, Obj args) Char * argv[MAX_ARGS + 2]; UInt i, len; Int pty; - len = LEN_LIST(args); + RequirePlainList(SELF_NAME, args); + len = LEN_PLIST(args); if (len > MAX_ARGS) ErrorQuit("Too many arguments", 0, 0); ConvString(dir); ConvString(prog); for (i = 1; i <= len; i++) { - allargs[i] = ELM_LIST(args, i); + allargs[i] = ELM_PLIST(args, i); ConvString(allargs[i]); } // From here we cannot afford to have a garbage collection @@ -1098,13 +1100,13 @@ FuncExecuteProcess(Obj self, Obj dir, Obj prg, Obj in, Obj out, Obj args) RequireStringRep(SELF_NAME, prg); Int iin = GetSmallInt(SELF_NAME, in); Int iout = GetSmallInt(SELF_NAME, out); - RequireSmallList(SELF_NAME, args); + RequirePlainList(SELF_NAME, args); // create an argument array - for (i = 1; i <= LEN_LIST(args); i++) { + for (i = 1; i <= LEN_PLIST(args); i++) { if (i == 1023) break; - tmp = ELM_LIST(args, i); + tmp = ELM_PLIST(args, i); RequireStringRep(SELF_NAME, tmp); ExecArgs[i] = tmp; } diff --git a/tst/testinstall/kernel/streams.tst b/tst/testinstall/kernel/streams.tst index ebf5349ae6..12a3859cf5 100644 --- a/tst/testinstall/kernel/streams.tst +++ b/tst/testinstall/kernel/streams.tst @@ -293,7 +293,7 @@ Error, ExecuteProcess: must be a small integer (not the value 'fail') gap> ExecuteProcess("","",0,fail,fail); Error, ExecuteProcess: must be a small integer (not the value 'fail') gap> ExecuteProcess("","",0,0,fail); -Error, ExecuteProcess: must be a small list (not the value 'fail') +Error, ExecuteProcess: must be a plain list (not the value 'fail') gap> ExecuteProcess("","",0,0,[1]); Error, ExecuteProcess: must be a string (not the integer 1) From 77f8ab0b714aef357c2fdfcefba2127ba4fe3b2b Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 6 Jun 2026 13:06:11 +0200 Subject: [PATCH 027/114] More kernel tweaks (#6428) * kernel: drop unused return value of UseTmpPerm * kernel: use BOOL in more places * kernel: init buffer with memset * kernel: use size_t in some places * kernel: explain certain uses of 'extern inline' * kernel: update some comments --- src/code.c | 1 + src/collectors.cc | 25 ++++++------- src/cyclotom.c | 1 + src/exprs.c | 1 + src/funcs.c | 1 + src/gaptime.c | 8 ++--- src/gvars.c | 16 ++++----- src/io.c | 2 +- src/lists.c | 56 ++++++++++++++--------------- src/main.c | 3 +- src/objcftl.c | 1 + src/objset.c | 8 ++--- src/opers.cc | 25 ++++++------- src/permutat.cc | 3 +- src/plist.c | 92 +++++++++++++++++++++++------------------------ src/profile.c | 2 +- src/read.c | 10 +++--- src/records.c | 2 +- src/scanner.c | 2 +- src/sortbase.h | 9 ++--- src/sysfiles.c | 24 ++++++------- src/sysstr.h | 13 +++---- src/tietze.c | 34 +++++++++--------- src/trans.cc | 13 +++---- src/weakptr.c | 4 +-- 25 files changed, 183 insertions(+), 173 deletions(-) diff --git a/src/code.c b/src/code.c index 5ff2315c98..40268f9de8 100644 --- a/src/code.c +++ b/src/code.c @@ -57,6 +57,7 @@ DECL_MODULE_STATE Int CountExpr; static ModuleStateOffset CodeStateOffset = -1; +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct CodeModuleState * CShelper(void) { return (struct CodeModuleState *)StateSlotsAtOffset(CodeStateOffset); diff --git a/src/collectors.cc b/src/collectors.cc index 3a8f37b314..c3561ea8db 100644 --- a/src/collectors.cc +++ b/src/collectors.cc @@ -63,6 +63,7 @@ DECL_MODULE_STATE UInt SC_MAX_STACK_SIZE; static ModuleStateOffset CollectorsStateOffset = -1; +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct CollectorsState_ * CollectorsState(void) { return (struct CollectorsState_ *)StateSlotsAtOffset(CollectorsStateOffset); @@ -380,7 +381,7 @@ static Int SingleCollectWord(Obj sc, Obj vv, Obj w) Obj tmp; // temporary obj for power - Int resized = 0;// indicates whether a Resize() happened + BOOL resized = FALSE;// indicates whether a Resize() happened // is the first non-trivial entry in start = SC_NUMBER_RWS_GENERATORS(sc); @@ -421,23 +422,23 @@ static Int SingleCollectWord(Obj sc, Obj vv, Obj w) const UInt desiredStackSize = sizeof(Obj) * (max + 2); if ( SIZE_OBJ(vnw) < desiredStackSize ) { ResizeBag( vnw, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vlw) < desiredStackSize ) { ResizeBag( vlw, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vpw) < desiredStackSize ) { ResizeBag( vpw, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vew) < desiredStackSize ) { ResizeBag( vew, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vge) < desiredStackSize ) { ResizeBag( vge, desiredStackSize ); - resized = 1; + resized = TRUE; } if( resized ) return -1; @@ -891,7 +892,7 @@ static Int CombiCollectWord(Obj sc, Obj vv, Obj w) Obj tmp; // temporary obj for power - Int resized = 0;// indicates whether a Resize() happened + BOOL resized = FALSE;// indicates whether a Resize() happened // if is the identity return now if ( NPAIRS_WORD(w) == 0 ) { @@ -929,23 +930,23 @@ static Int CombiCollectWord(Obj sc, Obj vv, Obj w) const UInt desiredStackSize = sizeof(Obj) * (max + 2); if ( SIZE_OBJ(vnw) < desiredStackSize ) { ResizeBag( vnw, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vlw) < desiredStackSize ) { ResizeBag( vlw, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vpw) < desiredStackSize ) { ResizeBag( vpw, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vew) < desiredStackSize ) { ResizeBag( vew, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vge) < desiredStackSize ) { ResizeBag( vge, desiredStackSize ); - resized = 1; + resized = TRUE; } if( resized ) return -1; diff --git a/src/cyclotom.c b/src/cyclotom.c index 3025530f94..e626946916 100644 --- a/src/cyclotom.c +++ b/src/cyclotom.c @@ -185,6 +185,7 @@ DECL_MODULE_STATE UInt LastNCyc; #ifdef HPCGAP }; // end of struct CycModuleState +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct CycModuleState *CycState(void) { return (struct CycModuleState *)StateSlotsAtOffset(CycStateOffset); diff --git a/src/exprs.c b/src/exprs.c index 2c234633ad..840d2d709b 100644 --- a/src/exprs.c +++ b/src/exprs.c @@ -66,6 +66,7 @@ DECL_MODULE_STATE UInt OldPrintPrecedence; static ModuleStateOffset ExprsStateOffset = -1; +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct ExprsState * ExprsState(void) { return (struct ExprsState *)StateSlotsAtOffset(ExprsStateOffset); diff --git a/src/funcs.c b/src/funcs.c index 62919177f5..16acf1fb93 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -50,6 +50,7 @@ struct FuncsModuleState { #ifdef HPCGAP }; +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct FuncsModuleState *FuncsState(void) { return (struct FuncsModuleState *)StateSlotsAtOffset(FuncsStateOffset); diff --git a/src/gaptime.c b/src/gaptime.c index c0fe220192..affa0895ac 100644 --- a/src/gaptime.c +++ b/src/gaptime.c @@ -267,17 +267,17 @@ static Obj FuncNanosecondsSinceEpochInfo(Obj self) Obj res, tmp; Int8 resolution; const char * method = "unsupported"; - Int monotonic = 0; + BOOL monotonic = FALSE; #if defined(__APPLE__) && defined(__MACH__) method = "mach_absolute_time"; - monotonic = 1; + monotonic = TRUE; #elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) method = "clock_gettime"; - monotonic = 1; + monotonic = TRUE; #elif defined(HAVE_GETTIMEOFDAY) method = "gettimeofday"; - monotonic = 0; + monotonic = FALSE; #endif res = NEW_PREC(4); diff --git a/src/gvars.c b/src/gvars.c index 5232cd2d21..76d2746c9b 100644 --- a/src/gvars.c +++ b/src/gvars.c @@ -675,7 +675,7 @@ void MakeThreadLocalVar ( if (IS_INTOBJ(ExprGVar(gvar))) value = (Obj) 0; SET_ELM_GVAR_LIST( ExprGVars, gvar, INTOBJ_INT(rnam) ); - SetHasExprCopiesFopies(gvar, 1); + SetHasExprCopiesFopies(gvar, TRUE); CHANGED_GVAR_LIST( ExprGVars, gvar ); if (value && TLVars) SetTLDefault(TLVars, rnam, value); @@ -690,7 +690,7 @@ void MakeThreadLocalVar ( Obj FuncDeclareGlobalName(Obj self, Obj name) { RequireStringRep("DeclareGlobalName", name); - SetIsDeclaredName(GVarName(CONST_CSTR_STRING(name)), 1); + SetIsDeclaredName(GVarName(CONST_CSTR_STRING(name)), TRUE); return 0; } @@ -854,7 +854,7 @@ static Obj FuncAUTO(Obj self, Obj args) gvar = GVarName( CONST_CSTR_STRING(name) ); SET_ELM_GVAR_LIST( ValGVars, gvar, 0 ); SET_ELM_GVAR_LIST( ExprGVars, gvar, list ); - SetHasExprCopiesFopies(gvar, 1); + SetHasExprCopiesFopies(gvar, TRUE); CHANGED_GVAR_LIST( ExprGVars, gvar ); } @@ -1063,7 +1063,7 @@ static Obj FuncUNB_GVAR(Obj self, Obj gvar) */ typedef struct { Obj * copy; - UInt isFopy; + BOOL isFopy; const Char * name; } StructCopyGVar; @@ -1105,7 +1105,7 @@ void InitCopyGVar ( Panic("no room to record CopyGVar"); } CopyAndFopyGVars[NCopyAndFopyGVars].copy = copy; - CopyAndFopyGVars[NCopyAndFopyGVars].isFopy = 0; + CopyAndFopyGVars[NCopyAndFopyGVars].isFopy = FALSE; CopyAndFopyGVars[NCopyAndFopyGVars].name = name; NCopyAndFopyGVars++; #ifdef HPCGAP @@ -1142,7 +1142,7 @@ void InitFopyGVar ( Panic("no room to record FopyGVar"); } CopyAndFopyGVars[NCopyAndFopyGVars].copy = copy; - CopyAndFopyGVars[NCopyAndFopyGVars].isFopy = 1; + CopyAndFopyGVars[NCopyAndFopyGVars].isFopy = TRUE; CopyAndFopyGVars[NCopyAndFopyGVars].name = name; NCopyAndFopyGVars++; #ifdef HPCGAP @@ -1186,7 +1186,7 @@ void UpdateCopyFopyInfo ( void ) MakeBagPublic(cops); #endif SET_ELM_GVAR_LIST( FopiesGVars, gvar, cops ); - SetHasExprCopiesFopies(gvar, 1); + SetHasExprCopiesFopies(gvar, TRUE); CHANGED_GVAR_LIST( FopiesGVars, gvar ); } } @@ -1198,7 +1198,7 @@ void UpdateCopyFopyInfo ( void ) MakeBagPublic(cops); #endif SET_ELM_GVAR_LIST( CopiesGVars, gvar, cops ); - SetHasExprCopiesFopies(gvar, 1); + SetHasExprCopiesFopies(gvar, TRUE); CHANGED_GVAR_LIST( CopiesGVars, gvar ); } } diff --git a/src/io.c b/src/io.c index f17e34e606..9484c39a01 100644 --- a/src/io.c +++ b/src/io.c @@ -471,7 +471,7 @@ UInt CloseInput(TypInputFile * input) // if the input stream supports seeking, update its position to // reflect the actual state of things: we may have read and buffered // more bytes than we actually processed - int offset = strlen(input->ptr); + size_t offset = strlen(input->ptr); // check for EOF if (input->ptr[0] == '\377' && input->ptr[1] == '\0') offset = 0; diff --git a/src/lists.c b/src/lists.c index feb5c1584c..969d82573e 100644 --- a/src/lists.c +++ b/src/lists.c @@ -2415,7 +2415,7 @@ static Int CheckInit ( { Int i; // loop variable Int j; // loop variable - Int success = 1; + BOOL success = TRUE; Int fnums[] = { FN_IS_DENSE, FN_IS_NDENSE, FN_IS_HOMOG, FN_IS_NHOMOG, @@ -2453,7 +2453,7 @@ static Int CheckInit ( if ( ClearFiltsTNums[i] == 0 ) { Pr( "#W ClearFiltsListTNums [%s] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2464,7 +2464,7 @@ static Int CheckInit ( if ( HasFiltListTNums[i][fnums[j]] == -1 ) { Pr( "#W HasFiltListTNums [%s] [%s] missing\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; HasFiltListTNums[i][fnums[j]] = 0; } } @@ -2477,7 +2477,7 @@ static Int CheckInit ( if ( SetFiltListTNums[i][fnums[j]] == 0 ) { Pr( "#W SetFiltListTNums [%s] [%s] missing\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } } } @@ -2489,7 +2489,7 @@ static Int CheckInit ( if ( ResetFiltListTNums[i][fnums[j]] == 0 ) { Pr( "#W ResetFiltListTNums [%s] [%s] missing\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } } } @@ -2508,7 +2508,7 @@ static Int CheckInit ( Pr( "#W ResetFiltListTNums [%s] [%s] failed to reset\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } } } @@ -2524,7 +2524,7 @@ static Int CheckInit ( Pr( "#W SetFiltListTNums [%s] [%s] must not change\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } } } @@ -2537,7 +2537,7 @@ static Int CheckInit ( if ( ClearFiltsTNums[i]+IMMUTABLE != ClearFiltsTNums[i+IMMUTABLE]) { Pr( "#W ClearFiltsTNums [%s] mismatch between mutable and immutable\n", (Int)TNAM_TNUM(i), 0 ); - success = 0; + success = FALSE; } for ( j = 0; j < ARRAY_SIZE(fnums); j++ ) { @@ -2545,21 +2545,21 @@ static Int CheckInit ( HasFiltListTNums[i+IMMUTABLE][fnums[j]]) { Pr( "#W HasFiltListTNums [%s] [%s] mismatch between mutable and immutable\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } if ( (SetFiltListTNums[i][fnums[j]] | IMMUTABLE) != SetFiltListTNums[i+IMMUTABLE][fnums[j]]) { Pr( "#W SetFiltListTNums [%s] [%s] mismatch between mutable and immutable\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } if ( (ResetFiltListTNums[i][fnums[j]] | IMMUTABLE) != ResetFiltListTNums[i+IMMUTABLE][fnums[j]]) { Pr( "#W ResetFiltListTNums [%s] [%s] mismatch between mutable and immutable\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } } @@ -2570,43 +2570,43 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ empty -> dense ] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( HasFiltListTNums[i][FN_IS_NDENSE] ) { Pr( "#W HasFiltListTNums [%s] [ empty + ndense ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( ! HasFiltListTNums[i][FN_IS_HOMOG] ) { Pr( "#W HasFiltListTNums [%s] [ empty -> homog ] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( HasFiltListTNums[i][FN_IS_NHOMOG] ) { Pr( "#W HasFiltListTNums [%s] [ empty + nhomog ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( ! HasFiltListTNums[i][FN_IS_SSORT] ) { Pr( "#W HasFiltListTNums [%s] [ empty -> ssort ] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( HasFiltListTNums[i][FN_IS_NSORT] ) { Pr( "#W HasFiltListTNums [%s] [ empty + nsort ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( HasFiltListTNums[i][FN_IS_TABLE] ) { Pr( "#W HasFiltListTNums [%s] [ empty + table ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2615,7 +2615,7 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ dense + ndense ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2624,13 +2624,13 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ ndense + homog ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( HasFiltListTNums[i][FN_IS_TABLE] ) { Pr( "#W HasFiltListTNums [%s] [ ndense + table ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2639,19 +2639,19 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ homog + nhomog ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( ! HasFiltListTNums[i][FN_IS_DENSE] ) { Pr( "#W HasFiltListTNums [%s] [ homog -> dense ] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( HasFiltListTNums[i][FN_IS_NDENSE] ) { Pr( "#W HasFiltListTNums [%s] [ homog + ndense ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2660,7 +2660,7 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ nhomog + table ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2669,13 +2669,13 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ table -> homog ] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( ! HasFiltListTNums[i][FN_IS_DENSE] ) { Pr( "#W HasFiltListTNums [%s] [ table -> dense ] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2684,7 +2684,7 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ ssort + nsort ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } } diff --git a/src/main.c b/src/main.c index 69d5e3dd95..0d1af37314 100644 --- a/src/main.c +++ b/src/main.c @@ -97,7 +97,6 @@ static void SetupGAPLocation(const char * argv0, char * GAPExecLocation) // In the code below, we keep resetting locBuf, as some of the methods we // try do not promise to leave the buffer empty on a failed return. char locBuf[GAP_PATH_MAX] = ""; - Int4 length = 0; #if defined(__APPLE__) && defined(__MACH__) uint32_t len = sizeof(locBuf); @@ -137,7 +136,7 @@ static void SetupGAPLocation(const char * argv0, char * GAPExecLocation) *GAPExecLocation = 0; // reset buffer after error // now strip the executable name off - length = strlen(GAPExecLocation); + size_t length = strlen(GAPExecLocation); while (length > 0 && GAPExecLocation[length] != '/') { GAPExecLocation[length] = 0; length--; diff --git a/src/objcftl.c b/src/objcftl.c index 472fd33772..83adcc9b13 100644 --- a/src/objcftl.c +++ b/src/objcftl.c @@ -44,6 +44,7 @@ struct CFTLModuleState { #ifdef HPCGAP }; +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct CFTLModuleState *CFTLState(void) { return (struct CFTLModuleState *)StateSlotsAtOffset(CFTLStateOffset); diff --git a/src/objset.c b/src/objset.c index d72eaa22c3..1d404a5c8a 100644 --- a/src/objset.c +++ b/src/objset.c @@ -127,7 +127,7 @@ static inline void WRITE_SLOT(Obj container, int slot, Obj elm) static void PrintObjSet(Obj set) { UInt i, size = CONST_ADDR_WORD(set)[OBJSET_SIZE]; - Int comma = 0; + BOOL comma = FALSE; Pr("OBJ_SET([ ", 0, 0); for (i=0; i < size; i++) { Obj obj = READ_SLOT(set, i); @@ -135,7 +135,7 @@ static void PrintObjSet(Obj set) if (comma) { Pr(", ", 0, 0); } else { - comma = 1; + comma = TRUE; } PrintObj(obj); } @@ -146,7 +146,7 @@ static void PrintObjSet(Obj set) static void PrintObjMap(Obj map) { UInt i, size = CONST_ADDR_WORD(map)[OBJSET_SIZE]; - Int comma = 0; + BOOL comma = FALSE; Pr("OBJ_MAP([ ", 0, 0); for (i=0; i < size; i++) { Obj obj = READ_SLOT(map, i * 2); @@ -154,7 +154,7 @@ static void PrintObjMap(Obj map) if (comma) { Pr(", ", 0, 0); } else { - comma = 1; + comma = TRUE; } PrintObj(obj); Pr(", ", 0, 0); diff --git a/src/opers.cc b/src/opers.cc index ce86f7a99d..e2e431f8c9 100644 --- a/src/opers.cc +++ b/src/opers.cc @@ -755,7 +755,8 @@ static Obj FuncWITH_HIDDEN_IMPS_FLAGS(Obj self, Obj flags) #ifdef HPCGAP RegionWriteLock(REGION(WITH_HIDDEN_IMPS_FLAGS_CACHE)); #endif - Int changed, i, lastand, stop; + BOOL changed; + Int i, lastand, stop; Int hidden_imps_length = LEN_PLIST(HIDDEN_IMPS) / 2; Int hash = INT_INTOBJ(FuncHASH_FLAGS(0, flags)) % HIDDEN_IMPS_CACHE_LENGTH; @@ -777,18 +778,18 @@ static Obj FuncWITH_HIDDEN_IMPS_FLAGS(Obj self, Obj flags) #ifdef COUNT_OPERS WITH_HIDDEN_IMPS_MISS++; #endif - changed = 1; + changed = TRUE; lastand = 0; - while(changed) + while (changed) { - changed = 0; + changed = FALSE; for (i = hidden_imps_length, stop = lastand; i > stop; i--) { if( IS_SUBSET_FLAGS(with, ELM_PLIST(HIDDEN_IMPS, i*2)) && !IS_SUBSET_FLAGS(with, ELM_PLIST(HIDDEN_IMPS, i*2-1)) ) { with = FuncAND_FLAGS(0, with, ELM_PLIST(HIDDEN_IMPS, i*2-1)); - changed = 1; + changed = TRUE; stop = 0; lastand = i; } @@ -847,7 +848,8 @@ static Obj FuncWITH_IMPS_FLAGS(Obj self, Obj flags) #ifdef HPCGAP RegionWriteLock(REGION(IMPLICATIONS_SIMPLE)); #endif - Int changed, lastand, i, j, stop, imps_length; + BOOL changed; + Int lastand, i, j, stop, imps_length; Int hash = INT_INTOBJ(FuncHASH_FLAGS(0, flags)) % IMPS_CACHE_LENGTH; Obj cacheval; Obj with = flags; @@ -886,11 +888,11 @@ static Obj FuncWITH_IMPS_FLAGS(Obj self, Obj flags) // the other implications have to be considered in a loop imps_length = LEN_PLIST(IMPLICATIONS_COMPOSED); - changed = 1; + changed = TRUE; lastand = imps_length+1; while(changed) { - changed = 0; + changed = FALSE; for (i = 1, stop = lastand; i < stop; i++) { imp = ELM_PLIST(IMPLICATIONS_COMPOSED, i); @@ -898,7 +900,7 @@ static Obj FuncWITH_IMPS_FLAGS(Obj self, Obj flags) !IS_SUBSET_FLAGS(with, ELM_PLIST(imp, 1)) ) { with = FuncAND_FLAGS(0, with, ELM_PLIST(imp, 1)); - changed = 1; + changed = TRUE; stop = imps_length+1; lastand = i; } @@ -1607,7 +1609,6 @@ static UInt CacheMissStatistics[CACHE_SIZE + 1][7]; template static Obj GetMethodCached(Obj cacheBag, Int prec, Obj ids[]) { - UInt typematch; Obj * cache; Obj method = 0; UInt i; @@ -1625,11 +1626,11 @@ static Obj GetMethodCached(Obj cacheBag, Int prec, Obj ids[]) for (i = target; i < cacheEntrySize * CACHE_SIZE; i += cacheEntrySize) { if (cache[i + 1] == INTOBJ_INT(prec)) { - typematch = 1; + BOOL typematch = TRUE; // This loop runs over the arguments, should be compiled away for (int j = 0; j < n; j++) { if (cache[i + j + 2] != ids[j]) { - typematch = 0; + typematch = FALSE; break; } } diff --git a/src/permutat.cc b/src/permutat.cc index ccd5cfe976..7f7bb034a2 100644 --- a/src/permutat.cc +++ b/src/permutat.cc @@ -113,13 +113,12 @@ DECL_MODULE_STATE Obj TmpPerm; #endif -static UInt1 * UseTmpPerm(UInt size) +static void UseTmpPerm(UInt size) { if (TmpPerm == (Obj)0) TmpPerm = NewBag(T_PERM4, size); else if (SIZE_BAG(TmpPerm) < size) ResizeBag(TmpPerm, size); - return (UInt1 *)(ADDR_OBJ(TmpPerm) + 1); } template diff --git a/src/plist.c b/src/plist.c index c05f9b147a..a9b6d0f7e5 100644 --- a/src/plist.c +++ b/src/plist.c @@ -255,19 +255,19 @@ static Int KTNumPlist(Obj list, Obj * famfirst) // look at the first element elm = ELM_PLIST( list, 1 ); if ( elm == 0 ) { - isDense = 0; + isDense = FALSE; } #ifdef HPCGAP else if ( !CheckReadAccess(elm) ) { - isHom = 0; - areMut = 1; - isTable = 0; + isHom = FALSE; + areMut = TRUE; + isTable = FALSE; } #endif else if (TEST_OBJ_FLAG(elm, OBJ_FLAG_TESTING)) { - isHom = 0; + isHom = FALSE; areMut = IS_PLIST_MUTABLE(elm); - isTable = 0; + isTable = FALSE; } else { #ifdef HPCGAP @@ -285,20 +285,20 @@ static Int KTNumPlist(Obj list, Obj * famfirst) family = FAMILY_TYPE( typeObj ); ktnumFirst = 0; } - isHom = 1; + isHom = TRUE; areMut = IS_MUTABLE_OBJ(elm); // if entry is a homogeneous list this might be a table or list if (ktnumFirst >= T_PLIST_HOM) { - isTable = 1; - isRect = 1; + isTable = TRUE; + isRect = TRUE; len = LEN_PLIST(elm); } else if (ktnumFirst == 0 && IS_HOMOG_LIST(elm)) { - isTable = 1; + isTable = TRUE; // only handle small lists as rectangular if (IS_SMALL_LIST(elm)) { - isRect = 1; + isRect = TRUE; len = LEN_LIST(elm); } } @@ -319,45 +319,45 @@ static Int KTNumPlist(Obj list, Obj * famfirst) for ( ; isDense && (isHom || ! areMut) && i <= lenList; i++ ) { elm = ELM_PLIST( list, i ); if ( elm == 0 ) { - isDense = 0; + isDense = FALSE; } #ifdef HPCGAP else if ( !CheckReadAccess(elm) ) { - isHom = 0; - areMut = 1; - isTable = 0; - isRect = 0; + isHom = FALSE; + areMut = TRUE; + isTable = FALSE; + isRect = FALSE; } #endif else if (TEST_OBJ_FLAG(elm, OBJ_FLAG_TESTING)) { - isHom = 0; + isHom = FALSE; areMut = (areMut || IS_PLIST_MUTABLE(elm)); - isTable = 0; - isRect = 0; + isTable = FALSE; + isRect = FALSE; } else { if (isHom) { loopTypeObj = TYPE_OBJ(elm); if ( loopTypeObj != typeObj && FAMILY_TYPE(loopTypeObj) != family ) { - isHom = 0; - isTable = 0; - isRect = 0; + isHom = FALSE; + isTable = FALSE; + isRect = FALSE; } if ( isTable ) { // check IS_PLIST first, as it is much cheaper if (IS_PLIST(elm)) { if (isRect && LEN_PLIST(elm) != len) { - isRect = 0; + isRect = FALSE; } } else if (IS_SMALL_LIST(elm)) { if (isRect && LEN_LIST(elm) != len) { - isRect = 0; + isRect = FALSE; } } else { - isTable = 0; - isRect = 0; + isTable = FALSE; + isRect = FALSE; } } } @@ -367,13 +367,13 @@ static Int KTNumPlist(Obj list, Obj * famfirst) // if we know it is not dense if (knownNDense) - isDense = 0; + isDense = FALSE; // otherwise if we don't know that it IS dense else if (!knownDense) for ( ; isDense && i <= lenList; i++ ) { elm = ELM_PLIST( list, i ); if ( elm == 0 ) { - isDense = 0; + isDense = FALSE; } } @@ -403,13 +403,13 @@ static Int KTNumPlist(Obj list, Obj * famfirst) else if (IS_FFE(ELM_PLIST(list,1))) { FF fld = FLD_FFE(ELM_PLIST(list,1)); - UInt isFFE = 1; + BOOL isFFE = TRUE; for (i = 2; i <= lenList; i++) { x = ELM_PLIST(list,i); if (!IS_FFE(x) || FLD_FFE(x) != fld) { - isFFE = 0; + isFFE = FALSE; break; } } @@ -446,8 +446,8 @@ static Int KTNumHomPlist(Obj list) Obj elm, x; // one element of Int i; // loop variable Int res; // result - Int isSSort; // list is (known to be) SSorted - Int isNSort; // list is (known to be) non-sorted + BOOL isSSort; // list is (known to be) SSorted + BOOL isNSort; // list is (known to be) non-sorted #ifdef HPCGAP if (!CheckWriteAccess(list)) { @@ -486,13 +486,13 @@ static Int KTNumHomPlist(Obj list) if (IS_FFE(elm)) { FF fld = FLD_FFE(ELM_PLIST(list,1)); - UInt isFFE = 1; + BOOL isFFE = TRUE; for (i = 2; i <= lenList; i++) { x = ELM_PLIST(list,i); if (!IS_FFE(x) || FLD_FFE(x) != fld) { - isFFE = 0; + isFFE = FALSE; break; } } @@ -509,10 +509,10 @@ static Int KTNumHomPlist(Obj list) if (!HAS_FILT_LIST(list, FN_IS_TABLE )) { if ( IS_HOMOG_LIST(elm) ) { - isTable = 1; + isTable = TRUE; if (IS_PLIST(elm)) { - isRect = 1; + isRect = TRUE; len = LEN_PLIST(elm); } } @@ -528,7 +528,7 @@ static Int KTNumHomPlist(Obj list) } else { - isTable = 1; + isTable = TRUE; isRect = HAS_FILT_LIST(list, FN_IS_RECT); } if (isTable && !isRect) @@ -1961,10 +1961,10 @@ static BOOL IsSSortPlist(Obj list) Int lenList; Obj elm1; Obj elm2; - Int areMut; + BOOL areMut; Int i; Obj fam=0; // initialize to help compiler - Int isHom; + BOOL isHom; // get the length lenList = LEN_PLIST( list ); @@ -1987,10 +1987,10 @@ static BOOL IsSSortPlist(Obj list) if (!SyInitializing) { fam = FAMILY_OBJ(elm1); - isHom = 1; + isHom = TRUE; } else - isHom = 0; + isHom = FALSE; // loop over the other elements for ( i = 2; i <= lenList; i++ ) { @@ -2047,10 +2047,10 @@ static BOOL IsSSortPlistDense(Obj list) Int lenList; Obj elm1; Obj elm2; - Int areMut; + BOOL areMut; Int i; Obj fam=0; // initialize to help compiler - Int isHom; + BOOL isHom; // get the length lenList = LEN_PLIST( list ); @@ -2071,10 +2071,10 @@ static BOOL IsSSortPlistDense(Obj list) if (!SyInitializing) { fam = FAMILY_OBJ(elm1); - isHom = 1; + isHom = TRUE; } else - isHom = 0; + isHom = FALSE; // loop over the other elements for ( i = 2; i <= lenList; i++ ) { @@ -2453,7 +2453,7 @@ static Obj FuncIsRectangularTablePlist(Obj self, Obj plist) Obj len; UInt lenlist; UInt i; - UInt hasMut = 0; + BOOL hasMut = FALSE; Obj elm; assert(!HAS_FILT_LIST(plist, FN_IS_RECT)); diff --git a/src/profile.c b/src/profile.c index c6c193adaa..bfd26913cb 100644 --- a/src/profile.c +++ b/src/profile.c @@ -430,7 +430,7 @@ void InformProfilingThatThisIsAForkedGAP(void) char filenamecpy[GAP_PATH_MAX]; // Allow 20 characters to allow space for .%d.gz const int SUPPORTED_PATH_LEN = GAP_PATH_MAX - 20; - if(strlen(profileState.filename) > SUPPORTED_PATH_LEN) { + if (strlen(profileState.filename) > SUPPORTED_PATH_LEN) { Panic("Filename can be at most %d character when forking", SUPPORTED_PATH_LEN); } if (endsWithgz(profileState.filename)) { diff --git a/src/read.c b/src/read.c index 1c12349574..437302919e 100644 --- a/src/read.c +++ b/src/read.c @@ -319,7 +319,7 @@ GAP_STATIC_ASSERT(sizeof(LHSRef) <= 8, "LHSRef is too big"); /**************************************************************************** ** */ -static UInt EvalRef(ReaderState * rs, const LHSRef ref, Int needExpr) +static UInt EvalRef(ReaderState * rs, const LHSRef ref, BOOL needExpr) { TRY_IF_NO_ERROR { @@ -643,7 +643,7 @@ static void ReadReferenceModifiers(ReaderState * rs, TypSymbolSet follow) // read one or more selectors while (IS_IN(rs->s.Symbol, S_LPAREN | S_LBRACK | S_LBRACE | S_DOT)) { LHSRef ref = ReadSelector(rs, follow, level); - level = EvalRef(rs, ref, 1); + level = EvalRef(rs, ref, TRUE); } } @@ -864,13 +864,13 @@ static void ReadCallVarAss(ReaderState * rs, TypSymbolSet follow, Char mode) while (IS_IN(rs->s.Symbol, S_LPAREN | S_LBRACK | S_LBRACE | S_DOT)) { // so the prefix was a reference - UInt level = EvalRef(rs, ref, 1); + UInt level = EvalRef(rs, ref, TRUE); ref = ReadSelector(rs, follow, level); } // if we need a reference if (mode == 'r' || (mode == 'x' && rs->s.Symbol != S_ASSIGN)) { - Int needExpr = mode == 'r' || !IS_IN(rs->s.Symbol, S_SEMICOLON); + BOOL needExpr = mode == 'r' || !IS_IN(rs->s.Symbol, S_SEMICOLON); EvalRef(rs, ref, needExpr); } @@ -2065,7 +2065,7 @@ static void ReadFor(ReaderState * rs, TypSymbolSet follow) // volatile LHSRef ref = ReadVar(rs, follow); if (ref.type != R_INVALID) - EvalRef(rs, ref, 1); + EvalRef(rs, ref, TRUE); CheckUnboundGlobal(rs, ref); // 'in' diff --git a/src/records.c b/src/records.c index e19befec0d..76546db9c1 100644 --- a/src/records.c +++ b/src/records.c @@ -64,7 +64,7 @@ static void NewRNamCallback(SymbolTable * symtab, UInt id, Obj name) */ UInt RNamName(const Char * name) { - UInt len = strlen(name); + size_t len = strlen(name); if (len > 1023) { // Note: We can't pass 'name' here, as it might get moved by garbage collection ErrorQuit("Record names must consist of at most 1023 characters", 0, 0); diff --git a/src/scanner.c b/src/scanner.c index cc607b7582..37e642bb77 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -71,7 +71,7 @@ static void SyntaxErrorOrWarning(ScannerState * s, // error is reported, so the pretty-printed context would leak // a literal 0xFF byte to *errout* with no caret to anchor it. const char * line = GetInputLineBuffer(s->input); - const UInt len = strlen(line); + const size_t len = strlen(line); const int line_is_sentinel = (len == 0 || line[0] == '\377'); if (!line_is_sentinel) { if (line[len-1] != '\n') diff --git a/src/sortbase.h b/src/sortbase.h index 069c97672c..4dfd9afefc 100644 --- a/src/sortbase.h +++ b/src/sortbase.h @@ -164,11 +164,11 @@ static inline void PREFIXNAME(Sort3)(SORT_FUNC_ARGS, Int a, Int b, Int c) { * to be moved, and store the partition_point in the argument * partition_point */ -static inline Int PREFIXNAME(Partition)(SORT_FUNC_ARGS, Int start, Int end, +static inline BOOL PREFIXNAME(Partition)(SORT_FUNC_ARGS, Int start, Int end, Int *partition_point) { Int left = start; Int right = end; - Int first_pass = 1; + BOOL first_pass = TRUE; SORT_CREATE_LOCAL(pivot); PREFIXNAME(Sort3)(SORT_ARGS, start, start / 2 + end / 2, end); @@ -198,7 +198,7 @@ static inline Int PREFIXNAME(Partition)(SORT_FUNC_ARGS, Int start, Int end, *partition_point = left; return first_pass; } - first_pass = 0; + first_pass = FALSE; SWAP_INDICES(SORT_ARGS, left, right); left++; @@ -275,7 +275,8 @@ static void PREFIXNAME(CheckBadPivot)(SORT_FUNC_ARGS, Int start, Int end, Int pi static void PREFIXNAME(QuickSort)(SORT_FUNC_ARGS, Int start, Int end, Int depth) { - Int pivot, first_pass; + Int pivot; + BOOL first_pass; if (end - start < 24) { PREFIXNAME(Insertion)(SORT_ARGS, start, end); diff --git a/src/sysfiles.c b/src/sysfiles.c index c2cf83db00..b65033dbe1 100644 --- a/src/sysfiles.c +++ b/src/sysfiles.c @@ -250,7 +250,7 @@ Int4 SyGAPCRC( const Char * name ) UInt4 new; Int4 ch; Int fid; - Int seen_nl; + BOOL seen_nl; // the CRC of a non existing file is 0 fid = SyFopen(name, "r", TRUE); @@ -260,7 +260,7 @@ Int4 SyGAPCRC( const Char * name ) // read in the file byte by byte and compute the CRC crc = 0x12345678L; - seen_nl = 0; + seen_nl = FALSE; while ( (ch = SyGetch(fid) )!= EOF ) { if ( ch == '\377' || ch == '\n' || ch == '\r' ) @@ -269,10 +269,10 @@ Int4 SyGAPCRC( const Char * name ) if ( seen_nl ) continue; else - seen_nl = 1; + seen_nl = TRUE; } else - seen_nl = 0; + seen_nl = FALSE; old = (crc >> 8) & 0x00FFFFFFL; new = syCcitt32[ ( (UInt4)( crc ^ ch ) ) & 0xff ]; crc = old ^ new; @@ -321,14 +321,14 @@ static Obj FuncCrcString(Obj self, Obj str) UInt4 i, len; const Char *ptr; Int4 ch; - Int seen_nl; + BOOL seen_nl; RequireStringRep(SELF_NAME, str); ptr = CONST_CSTR_STRING(str); len = GET_LEN_STRING(str); crc = 0x12345678L; - seen_nl = 0; + seen_nl = FALSE; for (i = 0; i < len; i++) { ch = (Int4)(ptr[i]); if ( ch == '\377' || ch == '\n' || ch == '\r' ) @@ -337,10 +337,10 @@ static Obj FuncCrcString(Obj self, Obj str) if ( seen_nl ) continue; else - seen_nl = 1; + seen_nl = TRUE; } else - seen_nl = 0; + seen_nl = FALSE; old = (crc >> 8) & 0x00FFFFFFL; new = syCcitt32[ ( (UInt4)( crc ^ ch ) ) & 0xff ]; crc = old ^ new; @@ -981,7 +981,7 @@ static UInt syLastIntr; // time of the last interrupt #ifdef HAVE_LIBREADLINE -static Int doingReadline; +static BOOL doingReadline; #endif static void syAnswerIntr(int signr) @@ -1207,7 +1207,7 @@ void SyFputs ( const Char * line, Int fid ) { - UInt i; + size_t i; // if outputting to the terminal compute the cursor position and length if ( fid == 1 || fid == 3 ) { @@ -2089,9 +2089,9 @@ static Char * readlineFgets(Char * line, UInt length, Int fid, UInt block) rl_event_hook = (OnCharReadHookActiveCheck()) ? charreadhook_rl : 0; #endif // now do the real work - doingReadline = 1; + doingReadline = TRUE; rlres = readline(STATE(Prompt)); - doingReadline = 0; + doingReadline = FALSE; // we get a NULL pointer on EOF, say by pressing Ctr-d if (!rlres) { if (!SyCTRD) { diff --git a/src/sysstr.h b/src/sysstr.h index c9173e5c8e..72ed52e687 100644 --- a/src/sysstr.h +++ b/src/sysstr.h @@ -23,8 +23,8 @@ ** *F IsAlpha( ) . . . . . . . . . . . . . is a character a normal letter ** -** 'IsAlpha' returns 1 if its character argument is a character from the -** range 'a..zA..Z' and 0 otherwise. +** 'IsAlpha' returns TRUE if its character argument is a character from the +** range 'a..zA..Z' and FALSE otherwise. */ #define IsAlpha(ch) (isalpha((unsigned int)ch)) @@ -33,8 +33,8 @@ ** *F IsDigit( ) . . . . . . . . . . . . . . . . . is a character a digit ** -** 'IsDigit' returns 1 if its character argument is a digit from the range -** '0..9' and 0 otherwise. +** 'IsDigit' returns TRUE if its character argument is a digit from the +** range '0..9' and FALSE otherwise. */ #define IsDigit(ch) (isdigit((unsigned int)ch)) @@ -43,8 +43,9 @@ ** *F IsIdent( ) . . . . . . . . is a character valid in a GAP identifier ** -** 'IsIdent' returns 1 if its character argument can be used unquoted inside -** a GAP identifier, i.e., is in the range 'a..zA..Z0-9_@', and 0 otherwise. +** 'IsIdent' returns TRUE if its character argument can be used unquoted +** inside a GAP identifier, i.e., is in the range 'a..zA..Z0-9_@', and +** FALSE otherwise. */ EXPORT_INLINE BOOL IsIdent(char ch) { diff --git a/src/tietze.c b/src/tietze.c index d86049a0ea..fa2ced13fa 100644 --- a/src/tietze.c +++ b/src/tietze.c @@ -289,7 +289,7 @@ static Obj FuncTzReplaceGens(Obj self, Obj tietze) Int total; // total length of relators Int old, new; // generators or inverses Int leng, reduced; // relator lengths - Int altered; // flag + BOOL altered; // flag Int i, j; // loop variables // check the Tietze stack @@ -317,7 +317,7 @@ static Obj FuncTzReplaceGens(Obj self, Obj tietze) rel = ptRels[i]; pt2 = ptRel = ADDR_OBJ( rel ); leng = INT_INTOBJ( ptLens[i] ); - altered = 0; + altered = FALSE; // don't change a square relator defining a valid involution if (ELM_PLIST(flags, i) == INTOBJ_INT(3) && leng == 2 && @@ -336,16 +336,18 @@ static Obj FuncTzReplaceGens(Obj self, Obj tietze) new = INT_INTOBJ( ptInvs[-old] ); if ( ! new ) { - altered = 1; + altered = TRUE; continue; // loop over j } if ( pt2 > ptRel && *pt2 == ptInvs[new] ) { - altered = 1; + altered = TRUE; --pt2; } else { - if ( new != old ) { altered = 1; } + if ( new != old ) { + altered = TRUE; + } *++pt2 = INTOBJ_INT( new ); } } @@ -973,9 +975,8 @@ static Obj FuncTzSearchC(Obj self, Obj args) Int n, m; // subword lengths Int count; // number of altered relators Int i, j, jj, x, y; // loop variables - Int lasty; // flag - Int altered; // flag - Int equal; // flag + Int lasty; // previous value of y + BOOL altered; // flag // get and check arguments if ( ! IS_SMALL_LIST(args) || 4 < LEN_LIST(args) || LEN_LIST(args) < 3 ) { @@ -1036,7 +1037,7 @@ static Obj FuncTzSearchC(Obj self, Obj args) ErrorQuit(" must be false or true", 0, 0); } } - equal = ( equ == True ); + const BOOL equal = ( equ == True ); // Skip relators of inconvenient lengths or with inconvenient flags, // and return if the remaining range is empty @@ -1072,8 +1073,9 @@ static Obj FuncTzSearchC(Obj self, Obj args) inv = 109109 * inv; // initialize the hash table - for ( i = 0; i < 2048; i++ ) - ((UInt4 *)keys1)[i] = ((UInt4 *)keys2)[i] = ((UInt4 *)keys3)[i] = 0; + memset(keys1, 0, sizeof(keys1)); + memset(keys2, 0, sizeof(keys2)); + memset(keys3, 0, sizeof(keys3)); // loop over the Tietze relators, starting at position pos1 for ( y = pos1; y < numrels; ) { @@ -1130,7 +1132,7 @@ static Obj FuncTzSearchC(Obj self, Obj args) ylen = INT_INTOBJ( ptLens[y] ); yflag = INT_INTOBJ( ptFlags[y] ); ylen1 = ylen - 1; - altered = 0; + altered = FALSE; // Loop to the next relator, if the current relator is too short if ( y > lasty @@ -1238,7 +1240,7 @@ static Obj FuncTzSearchC(Obj self, Obj args) } ptFlags[y] = INTOBJ_INT( newflag ); - altered = 1; + altered = TRUE; ++count; break; // loop over i } @@ -1285,7 +1287,7 @@ static Obj FuncTzSearchC(Obj self, Obj args) ptFlags = ADDR_OBJ( flags); ptInvs = ADDR_OBJ( invs ) + (numgens + 1); - altered = 1; + altered = TRUE; ++count; --y; break; // loop over i @@ -1331,7 +1333,7 @@ static Obj FuncTzSearchC(Obj self, Obj args) } ptFlags[y] = INTOBJ_INT( newflag ); - altered = 1; + altered = TRUE; ++count; break; // loop over i } @@ -1378,7 +1380,7 @@ static Obj FuncTzSearchC(Obj self, Obj args) ptFlags = ADDR_OBJ( flags); ptInvs = ADDR_OBJ( invs ) + numgens + 1; - altered = 1; + altered = TRUE; ++count; --y; break; // loop over i diff --git a/src/trans.cc b/src/trans.cc index 891a858598..557e7b02a5 100644 --- a/src/trans.cc +++ b/src/trans.cc @@ -3865,7 +3865,8 @@ Obj OnSetsTrans(Obj set, Obj f) const UInt4 * ptf4; UInt deg; Obj * ptres, tmp, res; - UInt i, isint, k; + UInt i, k; + BOOL isInt; // copy the list into a mutable plist, which we will then modify in place res = PLAIN_LIST_COPY(set); @@ -3876,7 +3877,7 @@ Obj OnSetsTrans(Obj set, Obj f) ptf2 = CONST_ADDR_TRANS2(f); deg = DEG_TRANS2(f); // loop over the entries of the tuple - isint = 1; + isInt = TRUE; for (i = 1; i <= len; i++, ptres++) { tmp = *ptres; if (IS_POS_INTOBJ(tmp)) { @@ -3886,7 +3887,7 @@ Obj OnSetsTrans(Obj set, Obj f) } } else { - isint = 0; + isInt = FALSE; tmp = POW(tmp, f); ptres = ADDR_OBJ(res) + i; ptf2 = CONST_ADDR_TRANS2(f); @@ -3900,7 +3901,7 @@ Obj OnSetsTrans(Obj set, Obj f) deg = DEG_TRANS4(f); // loop over the entries of the tuple - isint = 1; + isInt = TRUE; for (i = 1; i <= len; i++, ptres++) { tmp = *ptres; if (IS_POS_INTOBJ(tmp)) { @@ -3910,7 +3911,7 @@ Obj OnSetsTrans(Obj set, Obj f) } } else { - isint = 0; + isInt = FALSE; tmp = POW(tmp, f); ptres = ADDR_OBJ(res) + i; ptf4 = CONST_ADDR_TRANS4(f); @@ -3921,7 +3922,7 @@ Obj OnSetsTrans(Obj set, Obj f) } // sort the result and remove dups - if (isint) { + if (isInt) { SortPlistByRawObj(res); REMOVE_DUPS_PLIST_INTOBJ(res); RetypeBagSM(res, T_PLIST_CYC_SSORT); diff --git a/src/weakptr.c b/src/weakptr.c index 8d27774971..f99e8bde37 100644 --- a/src/weakptr.c +++ b/src/weakptr.c @@ -279,7 +279,7 @@ static Obj FuncWeakPointerObj(Obj self, Obj list) static Int LengthWPObj(Obj wp) { - Int changed = 0; + BOOL changed = FALSE; Int len = STORED_LEN_WPOBJ(wp); #ifdef HPCGAP if (!CheckExclusiveWriteAccess(wp)) @@ -291,7 +291,7 @@ static Int LengthWPObj(Obj wp) elm = ELM_WPOBJ(wp, len); if (elm) break; - changed = 1; + changed = TRUE; len--; } if (changed) From f1710d2725af0dcdbce062e1b1905aa6e08ec6e1 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 6 Jun 2026 13:06:50 +0200 Subject: [PATCH 028/114] kernel: remove `ErrorReturnObj`, `C_NEW_STRING` (#6415) * kernel: remove ErrorReturnObj, C_NEW_STRING We don't use them nor any distributed package. * remove stuff which is now also dead --- lib/error.g | 16 ++-------------- lib/methsel2.g | 1 - src/error.c | 20 +++----------------- src/error.h | 7 ------- src/stringobj.h | 12 ------------ 5 files changed, 5 insertions(+), 51 deletions(-) diff --git a/lib/error.g b/lib/error.g index de03ee813f..dbf522412a 100644 --- a/lib/error.g +++ b/lib/error.g @@ -228,7 +228,7 @@ end); # Unbind(ErrorInner); BIND_GLOBAL("ErrorInner", function(options, earlyMessage) - local context, tracebackContext, mayReturnVoid, mayReturnObj, + local context, tracebackContext, mayReturnVoid, lateMessage, x, prompt, res, errorLVars, errorTracebackLVars, kernelErrorLVars, justQuit, printEarlyMessage, printEarlyTraceback, printAutomaticTraceback, lastErrorStream; @@ -262,17 +262,6 @@ BIND_GLOBAL("ErrorInner", function(options, earlyMessage) mayReturnVoid := false; fi; - if IsBound(options.mayReturnObj) then - mayReturnObj := options.mayReturnObj; - if not mayReturnObj in [false, true] then - PrintTo(ERROR_OUTPUT, "ErrorInner: option mayReturnObj must be true or false\n"); - LEAVE_ALL_NAMESPACES(); - JUMP_TO_CATCH(1); - fi; - else - mayReturnObj := false; - fi; - if IsBound(options.tracebackContext) then tracebackContext := options.tracebackContext; if not IsLVarsBag(tracebackContext) then @@ -410,7 +399,7 @@ BIND_GLOBAL("ErrorInner", function(options, earlyMessage) prompt := "brk> "; fi; if not justQuit then - res := SHELL(context,mayReturnVoid,mayReturnObj,true,prompt,false); + res := SHELL(context,mayReturnVoid,false,true,prompt,false); else res := fail; fi; @@ -455,7 +444,6 @@ BIND_GLOBAL("ErrorNoReturn", function(arg) rec( context := ParentLVars(GetCurrentLVars()), mayReturnVoid := false, - mayReturnObj := false, lateMessage := "type 'quit;' to quit to outer loop", ), arg); diff --git a/lib/methsel2.g b/lib/methsel2.g index 51700574ea..45a5f471b0 100644 --- a/lib/methsel2.g +++ b/lib/methsel2.g @@ -252,7 +252,6 @@ end; context := GetCurrentLVars(), tracebackContext := ParentLVars(GetCurrentLVars()), mayReturnVoid := false, - mayReturnObj := false, lateMessage := "type 'quit;' to quit to outer loop" ), [ no_method_found ]); diff --git a/src/error.c b/src/error.c index 2618e32739..64371589f2 100644 --- a/src/error.c +++ b/src/error.c @@ -422,7 +422,6 @@ static Obj CallErrorInner(const Char * msg, Int arg2, UInt justQuit, UInt mayReturnVoid, - UInt mayReturnObj, Obj lateMessage) { // Must do this before creating any other GAP objects, @@ -447,7 +446,6 @@ static Obj CallErrorInner(const Char * msg, #endif AssPRec(r, RNamName("context"), STATE(CurrLVars)); AssPRec(r, RNamName("justQuit"), justQuit ? True : False); - AssPRec(r, RNamName("mayReturnObj"), mayReturnObj ? True : False); AssPRec(r, RNamName("mayReturnVoid"), mayReturnVoid ? True : False); AssPRec(r, RNamName("lateMessage"), lateMessage); l = NewPlistFromArgs(EarlyMsg); @@ -469,7 +467,7 @@ static Obj CallErrorInner(const Char * msg, void ErrorQuit(const Char * msg, Int arg1, Int arg2) { - CallErrorInner(msg, arg1, arg2, 1, 0, 0, False); + CallErrorInner(msg, arg1, arg2, 1, 0, False); Panic("ErrorQuit must not return"); } @@ -496,18 +494,6 @@ void ErrorMayQuitNrAtLeastArgs(Int narg, Int actual) } -/**************************************************************************** -** -*F ErrorReturnObj( , , , ) . . print and return obj -*/ -Obj ErrorReturnObj(const Char * msg, Int arg1, Int arg2, const Char * msg2) -{ - Obj LateMsg; - LateMsg = MakeString(msg2); - return CallErrorInner(msg, arg1, arg2, 0, 0, 1, LateMsg); -} - - /**************************************************************************** ** *F ErrorReturnVoid( , , , ) . . . print and return @@ -516,7 +502,7 @@ void ErrorReturnVoid(const Char * msg, Int arg1, Int arg2, const Char * msg2) { Obj LateMsg; LateMsg = MakeString(msg2); - CallErrorInner(msg, arg1, arg2, 0, 1, 0, LateMsg); + CallErrorInner(msg, arg1, arg2, 0, 1, LateMsg); // ErrorMode( msg, arg1, arg2, (Obj)0, msg2, 'x' ); } @@ -527,7 +513,7 @@ void ErrorReturnVoid(const Char * msg, Int arg1, Int arg2, const Char * msg2) void ErrorMayQuit(const Char * msg, Int arg1, Int arg2) { Obj LateMsg = MakeString("type 'quit;' to quit to outer loop"); - CallErrorInner(msg, arg1, arg2, 0, 0, 0, LateMsg); + CallErrorInner(msg, arg1, arg2, 0, 0, LateMsg); Panic("ErrorMayQuit must not return"); } diff --git a/src/error.h b/src/error.h index 7915e12756..d0d8749d97 100644 --- a/src/error.h +++ b/src/error.h @@ -69,13 +69,6 @@ void ErrorMayQuitNrArgs(Int narg, Int actual) NORETURN; void ErrorMayQuitNrAtLeastArgs(Int narg, Int actual) NORETURN; -/**************************************************************************** -** -*F ErrorReturnObj( , , , ) . . print and return obj -*/ -Obj ErrorReturnObj(const Char * msg, Int arg1, Int arg2, const Char * msg2); - - /**************************************************************************** ** *F ErrorReturnVoid( , , , ) . . . print and return diff --git a/src/stringobj.h b/src/stringobj.h index 9b28f61107..4071c06365 100644 --- a/src/stringobj.h +++ b/src/stringobj.h @@ -358,18 +358,6 @@ EXPORT_INLINE Obj MakeImmStringWithLen(const char * buf, size_t len) } -/**************************************************************************** -** -*F C_NEW_STRING( , , ) . . . . . . create GAP string -** -** This macro is deprecated and only provided for backwards compatibility -** with some package kernel extensions. Use 'MakeStringWithLen' and -** 'MakeImmStringWithLen' instead. -*/ -#define C_NEW_STRING(string,len,cstr) \ - string = MakeStringWithLen( (cstr), (len) ) - - /**************************************************************************** ** *F AppendCStr( , , ) . . append data in a buffer to a string From 871d4fc4af182d4dc4c9a046e59032ba480bd9a9 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 6 Jun 2026 13:07:33 +0200 Subject: [PATCH 029/114] Fix ConjugateGroup for matrix groups not defined over a field (#6425) --- lib/grpmat.gi | 7 ++++++- tst/testbugfix/2026-06-05-ConjugateGroup.tst | 13 +++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tst/testbugfix/2026-06-05-ConjugateGroup.tst diff --git a/lib/grpmat.gi b/lib/grpmat.gi index 65104b3aa4..69966bc7a2 100644 --- a/lib/grpmat.gi +++ b/lib/grpmat.gi @@ -1353,7 +1353,12 @@ InstallMethod( ConjugateGroup, ", ", IsCollsElms, if HasIsSubgroupSL( G ) then SetIsSubgroupSL( H, IsSubgroupSL( G ) ); fi; - F:= FieldOfMatrixList( [ g ] ); + + F:= DefaultScalarDomainOfMatrixList( [ g ] ); + if not IsField( F ) then + return H; + fi; + if HasInvariantBilinearForm( G ) then if not IsBound( ginv ) then ginv := g^-1; diff --git a/tst/testbugfix/2026-06-05-ConjugateGroup.tst b/tst/testbugfix/2026-06-05-ConjugateGroup.tst new file mode 100644 index 0000000000..bd8e9c0783 --- /dev/null +++ b/tst/testbugfix/2026-06-05-ConjugateGroup.tst @@ -0,0 +1,13 @@ +# Fix an unexpected error in ConjugateGroup when applied to +# a matrix group not over a field +# See https://github.com/gap-system/gap/issues/6423 +gap> G:=SL(2,Integers mod 4);; +gap> H:=ConjugateGroup(G,G.1);; +gap> G = H; +true + +# original test case +gap> S := SylowSubgroup(SL(2,Integers mod 4),2);; +gap> M := MaximalSubgroups(S);; +gap> Length(M); +3 From 834868ea5cf3247f970bd9afc54f65915150b736 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 8 Jun 2026 11:15:49 +0200 Subject: [PATCH 030/114] kernel: improve `ErrorReturnVoid` break-loop message (#6416) ... and in general make its phrasing more consistent. Also update some several outdated sections of the documentation about break loops and error handling. Co-authored-by: Codex --- doc/ref/debug.xml | 18 ++++++++----- doc/ref/language.xml | 10 +++---- doc/ref/mloop.xml | 36 +++++++------------------ doc/ref/types.xml | 10 +++---- doc/tut/lists.xml | 9 +++---- lib/list.gd | 16 +++-------- src/cyclotom.c | 2 +- src/error.c | 15 ++++++----- src/funcs.c | 3 +-- src/hpc/thread.c | 2 +- src/stats.c | 20 +++++++------- src/streams.c | 18 +++++-------- src/vec8bit.c | 11 ++++---- src/vecgf2.c | 4 +-- tst/testspecial/mem-overflow.g.out | 3 ++- tst/testspecial/stack-depth-func.g.out | 6 +++-- tst/testspecial/stack-depth-func2.g.out | 6 +++-- tst/testspecial/stack-depth-rec.g.out | 6 +++-- 18 files changed, 86 insertions(+), 109 deletions(-) diff --git a/doc/ref/debug.xml b/doc/ref/debug.xml index 7121efabd7..e947af8d05 100644 --- a/doc/ref/debug.xml +++ b/doc/ref/debug.xml @@ -923,7 +923,8 @@ Error, recursion depth trap (5000) [2] dive( depth - 1 ); @ *stdin*:1 ... at *stdin*:4 -you may 'return;' +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue brk> return; gap> dive(11000); Error, recursion depth trap (5000) @@ -932,7 +933,8 @@ Error, recursion depth trap (5000) [2] dive( depth - 1 ); @ *stdin*:1 ... at *stdin*:5 -you may 'return;' +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue brk> return; Error, recursion depth trap (10000) *[1] dive( depth - 1 ); @@ -940,8 +942,10 @@ Error, recursion depth trap (10000) [2] dive( depth - 1 ); @ *stdin*:1 ... at *stdin*:5 -you may 'return;' -brk> return;gap> +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> return; +gap> ]]>

@@ -981,7 +985,8 @@ Error, recursion depth trap (1000) [2] dive( depth - 1 ); @ *stdin*:4 ... at *stdin*:12 -you may 'return;' +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue brk> return; Error, recursion depth trap (2000) *[1] dive( depth - 1 ); @@ -989,7 +994,8 @@ Error, recursion depth trap (2000) [2] dive( depth - 1 ); @ *stdin*:4 ... at *stdin*:12 -you may 'return;' +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue brk> GetRecursionDepth(); 0 brk> return; diff --git a/doc/ref/language.xml b/doc/ref/language.xml index cab355969b..cce1a2fbfc 100644 --- a/doc/ref/language.xml +++ b/doc/ref/language.xml @@ -715,11 +715,10 @@ gap> xx := 15; 15 gap> MakeReadOnlyGlobal("xx"); gap> xx := 16; -Variable: 'xx' is read only -not in any function -Entering break read-eval-print loop ... -you can 'quit;' to quit to outer loop, or -you can 'return;' after making it writable to continue +Error, Variable: 'xx' is read only +Stack trace: +not in any function at *stdin*:3 +type 'quit;' to quit to outer loop brk> quit; gap> IsReadOnlyGlobal("xx"); true @@ -1563,6 +1562,7 @@ gap> f2:= function( x ) return f1( x ); end;; gap> f2( 4 ); value: 4 Error, Function Calls: must return a value +Stack trace: *[1] f1( x ) @ *stdin*:2 ( ) diff --git a/doc/ref/mloop.xml b/doc/ref/mloop.xml index b39f2f50e8..ee80492a0b 100644 --- a/doc/ref/mloop.xml +++ b/doc/ref/mloop.xml @@ -477,6 +477,7 @@ indicate that you are in a break loop. 1/0; Error, Rational operations: must not be zero +Stack trace: not in any function at *stdin*:2 type 'quit;' to quit to outer loop ]]> @@ -487,7 +488,8 @@ If errors occur within a break loop &GAP; enters another break loop at a 1/0; Error, Rational operations: must not be zero -not in any function at *stdin*:2 +Stack trace: +not in any function at *errin*:1 type 'quit;' to quit to outer loop brk_2> ]]> @@ -537,25 +539,11 @@ purpose of this function. return return from break loop The other way to leave a break loop is to return from a break loop. -To do this you type return; or return obj;. If the break loop was entered because you interrupted &GAP;, then you can continue by typing return;. -If the break loop was entered due to an error, -you may have to modify the value of a variable before typing return; -(see the example for ) or you may have to -return an object obj -(by typing: return obj;) to continue the computation; -in any case, the message printed on entering the break loop will -tell you which of these alternatives is possible. -For example, if the break loop was entered because a variable had no -assigned value, the value to be returned is often a value that this -variable should have to continue the computation. -

- return 9; # we had tried to enter the divisor 9 but typed 0 ... -1/9 -gap> -]]> +If the break loop was entered due to an error, this option may or may not +be available, depending on the kind of error. The message printed on entering +the break loop will tell you whether this possible. @@ -581,7 +569,6 @@ function( ) ... end gap> Error("!\n"); Error, ! Hello -Entering break read-eval-print loop ... you can 'quit;' to quit to outer loop, or you can 'return;' to continue brk> quit; @@ -606,8 +593,7 @@ emitted at level 1

Note that for break loops entered by a call to , -the lines after Entering break read-eval-print loop ... -and before the brk> prompt can also be customised, +the lines just before the brk> prompt can also be customised, namely by redefining .

ErrorNoTraceBack @@ -649,7 +635,6 @@ Here is a somewhat trivial demonstration of the use of ErrorNoTraceBack("Gidday!", " How's", " it", " going?\n"); Error, Gidday! How's it going? -Entering break read-eval-print loop ... you can 'quit;' to quit to outer loop, or you can 'return;' to continue brk> quit; @@ -661,7 +646,6 @@ Now we call with the same arguments to show the difference. gap> Error("Gidday!", " How's", " it", " going?\n"); Error, Gidday! How's it going? Hello -Entering break read-eval-print loop ... you can 'quit;' to quit to outer loop, or you can 'return;' to continue brk> quit; @@ -685,9 +669,8 @@ gap> OnBreak := Where;; Break loop message When a break loop is entered by a call to -the message after the -Entering break read-eval-print loop ... line is produced -by the function OnBreakMessage, +the message at the end starting with you can 'quit;' to ... +is produced by the function OnBreakMessage, which just like is a user-configurable global variable that is a function with no arguments. @@ -718,7 +701,6 @@ calling as we did above, now produces: gap> Error("!\n"); Error, ! Hello -Entering break read-eval-print loop ... brk> quit; # to get back to outer loop ]]>

diff --git a/doc/ref/types.xml b/doc/ref/types.xml index 32ffe77b0c..b35730b539 100644 --- a/doc/ref/types.xml +++ b/doc/ref/types.xml @@ -601,12 +601,10 @@ for an object.

Setter( prop )( Rationals, false ); -You cannot set an "and-filter" except to true -not in any function -Entering break read-eval-print loop ... -you can 'quit;' to quit to outer loop, or -you can type 'return true;' to set all components true -(but you might really want to reset just one component) to continue +Error, You cannot set an "and-filter" except to true +Stack trace: +not in any function at *stdin*:8 +type 'quit;' to quit to outer loop brk> ]]> diff --git a/doc/tut/lists.xml b/doc/tut/lists.xml index d79908c21e..de893722ef 100644 --- a/doc/tut/lists.xml +++ b/doc/tut/lists.xml @@ -341,11 +341,10 @@ gap> list[3][5] := 'w';; list; copy; [ 1, 2, "threw", [ 4 ] ] [ 1, 2, "three", [ 4 ] ] gap> copy[3][5] := 'w'; -List Assignment: must be a mutable list -not in any function -Entering break read-eval-print loop ... -you can 'quit;' to quit to outer loop, or -you can 'return;' and ignore the assignment to continue +Error, List Assignment: must be a mutable list +Stack trace: +not in any function at *stdin*:3 +type 'quit;' to quit to outer loop brk> quit; ]]>

diff --git a/lib/list.gd b/lib/list.gd index 5a44805bae..f595715899 100644 --- a/lib/list.gd +++ b/lib/list.gd @@ -379,7 +379,7 @@ DeclareSynonym( "AsSSortedListList", AS_LIST_SORTED_LIST ); ## Lists with holes are sometimes convenient when the list represents ## a mapping from a finite, but not consecutive, ## subset of the positive integers. -## IsDenseList( [ 1, 2, 3 ] ); ## true ## gap> l := [ , 4, 9,, 25,, 49,,,, 121 ];; IsDenseList( l ); @@ -387,22 +387,12 @@ DeclareSynonym( "AsSSortedListList", AS_LIST_SORTED_LIST ); ## gap> l[3]; ## 9 ## gap> l[4]; -## List Element: [4] must have an assigned value -## not in any function -## Entering break read-eval-print loop ... -## you can 'quit;' to quit to outer loop, or -## you can 'return;' after assigning a value to continue -## brk> l[4] := 16;; # assigning a value -## brk> return; # to escape the break-loop -## 16 -## gap> -## ]]> +## Error, List Element: [4] must have an assigned value +## ]]> ##

## Observe that requesting the value of l[4], which was not ## assigned, caused the entry of a break-loop ## (see Section ). -## After assigning a value and typing return;, &GAP; is finally -## able to comply with our request (by responding with 16). ## ## ## <#/GAPDoc> diff --git a/src/cyclotom.c b/src/cyclotom.c index e626946916..9c56dde8e3 100644 --- a/src/cyclotom.c +++ b/src/cyclotom.c @@ -836,7 +836,7 @@ static UInt FindCommonField(UInt nl, UInt nr, UInt *ml, UInt *mr) "This computation requires a cyclotomic field of degree %d, larger " "than the current limit of %d", n, (Int)CyclotomicsLimit, - "You may return after raising the limit with SetCyclotomicsLimit"); + "you can 'return;' after raising the limit with SetCyclotomicsLimit"); } // Finish up diff --git a/src/error.c b/src/error.c index 64371589f2..b783458689 100644 --- a/src/error.c +++ b/src/error.c @@ -500,10 +500,13 @@ void ErrorMayQuitNrAtLeastArgs(Int narg, Int actual) */ void ErrorReturnVoid(const Char * msg, Int arg1, Int arg2, const Char * msg2) { - Obj LateMsg; - LateMsg = MakeString(msg2); - CallErrorInner(msg, arg1, arg2, 0, 1, LateMsg); - // ErrorMode( msg, arg1, arg2, (Obj)0, msg2, 'x' ); + if (msg2 == 0) { + msg2 = "you can 'return;' to continue"; + } + + Obj lateMsg = MakeString("you can 'quit;' to quit to outer loop, or\n"); + AppendString(lateMsg, MakeString(msg2)); + CallErrorInner(msg, arg1, arg2, 0, 1, lateMsg); } /**************************************************************************** @@ -634,7 +637,7 @@ void ErrorBoundedInt( void AssertionFailure(void) { - ErrorReturnVoid("Assertion failure", 0, 0, "you may 'return;'"); + ErrorReturnVoid("Assertion failure", 0, 0, 0); } void AssertionFailureWithMessage(Obj message) @@ -645,7 +648,7 @@ void AssertionFailureWithMessage(Obj message) AssertionFailure(); } else if (IS_STRING_REP(message)) { - ErrorReturnVoid("Assertion failure: %g", (Int)message, 0, "you may 'return;'"); + ErrorReturnVoid("Assertion failure: %g", (Int)message, 0, 0); } else { PrintObj(message); diff --git a/src/funcs.c b/src/funcs.c index 16acf1fb93..4d585e5bb2 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -387,8 +387,7 @@ void RecursionDepthTrap( void ) if (GetRecursionDepth() > 0) { recursionDepth = GetRecursionDepth(); SetRecursionDepth(0); - ErrorReturnVoid("recursion depth trap (%d)", (Int)recursionDepth, 0, - "you may 'return;'"); + ErrorReturnVoid("recursion depth trap (%d)", (Int)recursionDepth, 0, 0); SetRecursionDepth(recursionDepth); } } diff --git a/src/hpc/thread.c b/src/hpc/thread.c index 420074bf93..67f5219fda 100644 --- a/src/hpc/thread.c +++ b/src/hpc/thread.c @@ -975,7 +975,7 @@ static void InterruptCurrentThread(int locked, Stat stat) if (handler) CALL_WITH_CATCH(handler, NEW_PLIST(T_PLIST, 0)); else - ErrorReturnVoid("system interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("system interrupt", 0, 0, 0); if (!locked) pthread_mutex_unlock(thread->lock); } diff --git a/src/stats.c b/src/stats.c index fb2de23a1b..7ed53a74ce 100644 --- a/src/stats.c +++ b/src/stats.c @@ -392,7 +392,7 @@ static ALWAYS_INLINE ExecStatus ExecForHelper(Stat stat, UInt nr) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -435,7 +435,7 @@ static ALWAYS_INLINE ExecStatus ExecForHelper(Stat stat, UInt nr) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -530,7 +530,7 @@ static ALWAYS_INLINE ExecStatus ExecForRangeHelper(Stat stat, UInt nr) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -666,7 +666,7 @@ static ALWAYS_INLINE ExecStatus ExecWhileHelper(Stat stat, UInt nr) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -737,7 +737,7 @@ static ALWAYS_INLINE ExecStatus ExecRepeatHelper(Stat stat, UInt nr) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -952,7 +952,7 @@ static ExecStatus ExecReturnObj(Stat stat) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -980,7 +980,7 @@ static ExecStatus ExecReturnVoid(Stat stat) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -1027,7 +1027,7 @@ UInt TakeInterrupt( void ) { if (HaveInterrupt()) { UnInterruptExecStat(); - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); return 1; } return 0; @@ -1067,12 +1067,12 @@ static ExecStatus ExecIntrStat(Stat stat) if (printError) { ErrorReturnVoid("reached the pre-set memory limit\n" "(change it with the -o command line option)", - 0, 0, "you can 'return;'"); + 0, 0, 0); } } else #endif - ErrorReturnVoid( "user interrupt", 0, 0, "you can 'return;'" ); + ErrorReturnVoid("user interrupt", 0, 0, 0); #endif // continue at the interrupted statement diff --git a/src/streams.c b/src/streams.c index d36d67eb46..4750f3dec2 100644 --- a/src/streams.c +++ b/src/streams.c @@ -517,8 +517,7 @@ static Obj FuncLOG_TO(Obj self, Obj filename) { RequireStringRep(SELF_NAME, filename); if ( ! OpenLog( CONST_CSTR_STRING(filename) ) ) { - ErrorReturnVoid("LogTo: cannot log to %g", (Int)filename, 0, - "you can 'return;'"); + ErrorReturnVoid("LogTo: cannot log to %g", (Int)filename, 0, 0); return False; } return True; @@ -533,8 +532,7 @@ static Obj FuncLOG_TO_STREAM(Obj self, Obj stream) { RequireOutputStream(SELF_NAME, stream); if ( ! OpenLogStream(stream) ) { - ErrorReturnVoid("LogTo: cannot log to stream", 0, 0, - "you can 'return;'"); + ErrorReturnVoid("LogTo: cannot log to stream", 0, 0, 0); return False; } return True; @@ -578,8 +576,7 @@ static Obj FuncINPUT_LOG_TO(Obj self, Obj filename) { RequireStringRep(SELF_NAME, filename); if ( ! OpenInputLog( CONST_CSTR_STRING(filename) ) ) { - ErrorReturnVoid("InputLogTo: cannot log to %g", (Int)filename, 0, - "you can 'return;'"); + ErrorReturnVoid("InputLogTo: cannot log to %g", (Int)filename, 0, 0); return False; } return True; @@ -594,8 +591,7 @@ static Obj FuncINPUT_LOG_TO_STREAM(Obj self, Obj stream) { RequireOutputStream(SELF_NAME, stream); if ( ! OpenInputLogStream(stream) ) { - ErrorReturnVoid("InputLogTo: cannot log to stream", 0, 0, - "you can 'return;'"); + ErrorReturnVoid("InputLogTo: cannot log to stream", 0, 0, 0); return False; } return True; @@ -639,8 +635,7 @@ static Obj FuncOUTPUT_LOG_TO(Obj self, Obj filename) { RequireStringRep(SELF_NAME, filename); if ( ! OpenOutputLog( CONST_CSTR_STRING(filename) ) ) { - ErrorReturnVoid("OutputLogTo: cannot log to %g", (Int)filename, 0, - "you can 'return;'"); + ErrorReturnVoid("OutputLogTo: cannot log to %g", (Int)filename, 0, 0); return False; } return True; @@ -655,8 +650,7 @@ static Obj FuncOUTPUT_LOG_TO_STREAM(Obj self, Obj stream) { RequireOutputStream(SELF_NAME, stream); if ( ! OpenOutputLogStream(stream) ) { - ErrorReturnVoid("OutputLogTo: cannot log to stream", 0, 0, - "you can 'return;'"); + ErrorReturnVoid("OutputLogTo: cannot log to stream", 0, 0, 0); return False; } return True; diff --git a/src/vec8bit.c b/src/vec8bit.c index 3b50507c67..1b583895a8 100644 --- a/src/vec8bit.c +++ b/src/vec8bit.c @@ -3002,7 +3002,7 @@ void ASS_VEC8BIT(Obj list, Obj pos, Obj elm) ErrorReturnVoid("List assignment would increase length of " "locked compressed vector", 0, 0, - "You can `return;' to ignore the assignment"); + "you can 'return;' to ignore the assignment"); return; } ResizeWordSizedBag(list, SIZE_VEC8BIT(p, elts)); @@ -3094,7 +3094,7 @@ static Obj FuncUNB_VEC8BIT(Obj self, Obj list, Obj pos) if (True == DoFilter(IsLockedRepresentationVector, list)) { ErrorReturnVoid( "Unbind of entry of locked compressed vector is forbidden", 0, 0, - "You can `return;' to ignore the assignment"); + "you can 'return;' to ignore the assignment"); return 0; } @@ -3220,7 +3220,7 @@ static Obj FuncAPPEND_VEC8BIT(Obj self, Obj vecl, Obj vecr) lenr = LEN_VEC8BIT(vecr); if (True == DoFilter(IsLockedRepresentationVector, vecl) && lenr > 0) { ErrorReturnVoid("Append to locked compressed vector is forbidden", 0, - 0, "You can `return;' to ignore the operation"); + 0, "you can 'return;' to ignore the operation"); return 0; } info = GetFieldInfo8Bit(FIELD_VEC8BIT(vecl)); @@ -4369,7 +4369,7 @@ static void ResizeVec8Bit(Obj vec, UInt newlen, UInt knownclean) if (True == DoFilter(IsLockedRepresentationVector, vec)) { ErrorReturnVoid("Resize of locked compressed vector is forbidden", 0, - 0, "You can `return;' to ignore the operation"); + 0, "you can 'return;' to ignore the operation"); return; } @@ -5002,8 +5002,7 @@ static Obj MakeShiftedVecs(Obj v, UInt len) ResizeVec8Bit(vn, len, 0); len1 = (len == 0) ? 0 : RightMostNonZeroVec8Bit(vn); if (len1 == 0) - ErrorReturnVoid("Zero coefficient vector for reduction", 0, 0, - "you can 'return;'"); + ErrorReturnVoid("Zero coefficient vector for reduction", 0, 0, 0); if (len1 != len) { ResizeVec8Bit(vn, len1, 1); len = len1; diff --git a/src/vecgf2.c b/src/vecgf2.c index b3c7454cb0..c484531c5f 100644 --- a/src/vecgf2.c +++ b/src/vecgf2.c @@ -3826,7 +3826,7 @@ FuncREDUCE_COEFFS_GF2VEC(Obj self, Obj vec1, Obj len1, Obj vec2, Obj len2) if (len2a == 0) { ErrorReturnVoid("ReduceCoeffs: second argument must not be zero", 0, - 0, "you may 'return;' to skip the reduction"); + 0, "you can 'return;' to skip the reduction"); return 0; } @@ -3872,7 +3872,7 @@ FuncQUOTREM_COEFFS_GF2VEC(Obj self, Obj vec1, Obj len1, Obj vec2, Obj len2) } if (len2a == 0) { ErrorReturnVoid("QuotremCoeffs: second argument must not be zero", 0, - 0, "you may 'return;' to skip the reduction"); + 0, "you can 'return;' to skip the reduction"); return 0; } diff --git a/tst/testspecial/mem-overflow.g.out b/tst/testspecial/mem-overflow.g.out index 82620ab76a..1f9147a44c 100644 --- a/tst/testspecial/mem-overflow.g.out +++ b/tst/testspecial/mem-overflow.g.out @@ -7,7 +7,8 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:3 -you can 'return;' +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue brk> # ... then we should be in a break loop. Exit that, perform some other computations. brk> quit; gap> Factorial(42); diff --git a/tst/testspecial/stack-depth-func.g.out b/tst/testspecial/stack-depth-func.g.out index 60ab11d2a3..37a8116566 100644 --- a/tst/testspecial/stack-depth-func.g.out +++ b/tst/testspecial/stack-depth-func.g.out @@ -14,7 +14,8 @@ Stack trace: [5] f( ); @ *stdin*:2 ... at *stdin*:3 -you may 'return;' +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue brk> return; # try once more Error, recursion depth trap (10000) Stack trace: @@ -29,5 +30,6 @@ Stack trace: [5] f( ); @ *stdin*:2 ... at *stdin*:3 -you may 'return;' +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue brk> QUIT; diff --git a/tst/testspecial/stack-depth-func2.g.out b/tst/testspecial/stack-depth-func2.g.out index 7027f3df17..d41cac1c18 100644 --- a/tst/testspecial/stack-depth-func2.g.out +++ b/tst/testspecial/stack-depth-func2.g.out @@ -14,7 +14,8 @@ Stack trace: [5] f( ) @ *stdin*:2 ... at *stdin*:3 -you may 'return;' +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue brk> return; # try once more Error, recursion depth trap (10000) Stack trace: @@ -29,5 +30,6 @@ Stack trace: [5] f( ) @ *stdin*:2 ... at *stdin*:3 -you may 'return;' +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue brk> QUIT; diff --git a/tst/testspecial/stack-depth-rec.g.out b/tst/testspecial/stack-depth-rec.g.out index af205e7582..3a2f0bcb5a 100644 --- a/tst/testspecial/stack-depth-rec.g.out +++ b/tst/testspecial/stack-depth-rec.g.out @@ -82,7 +82,8 @@ Stack trace: [5] String( record.(nam) ) @ GAPROOT/lib/record.gi:LINE ... at *stdin*:4 -you may 'return;' +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue brk> return; # try once more Error, recursion depth trap (5000) Stack trace: @@ -97,5 +98,6 @@ Stack trace: [5] String( record.(nam) ) @ GAPROOT/lib/record.gi:LINE ... at *stdin*:4 -you may 'return;' +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue brk> QUIT; From dece20419f1f324a5c634688721b448422a0f983 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 8 Jun 2026 12:10:32 +0200 Subject: [PATCH 031/114] kernel: refactor FuncPRINT_CURRENT_STATEMENT (#6424) Move part of the code from the kernel to the library. This will make future improvements easier. Co-authored-by: Codex --- lib/error.g | 13 ++++++++--- src/error.c | 42 ++++++++++++++-------------------- tst/testinstall/kernel/gap.tst | 2 +- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/lib/error.g b/lib/error.g index dbf522412a..2a942b4fec 100644 --- a/lib/error.g +++ b/lib/error.g @@ -135,7 +135,8 @@ BIND_GLOBAL("PRETTY_PRINT_VARS", function(context) end); BIND_GLOBAL("WHERE", function(depth, context, activecontext, showlocals) - local bottom, lastcontext, f, level, totaldepth, countcontext; + local bottom, lastcontext, f, level, totaldepth, countcontext, + prefixwidth, location; if depth <= 0 then return; fi; @@ -151,14 +152,20 @@ BIND_GLOBAL("WHERE", function(depth, context, activecontext, showlocals) totaldepth := totaldepth + 1; countcontext := ParentLVars(countcontext); od; + prefixwidth := Length(String(totaldepth)); level := 1; while depth > 0 and context <> bottom do - PRINT_CURRENT_STATEMENT( + location := PRINT_CURRENT_STATEMENT( ERROR_OUTPUT, context, activecontext, level, - totaldepth); + prefixwidth); + if location <> fail then + PrintTo(ERROR_OUTPUT, "\n", + ListWithIdenticalEntries(prefixwidth+2, ' '), + "@ ", location[1], ":", location[2]); + fi; if showlocals then PRETTY_PRINT_VARS(context); else diff --git a/src/error.c b/src/error.c index b783458689..b392cd4302 100644 --- a/src/error.c +++ b/src/error.c @@ -184,12 +184,17 @@ static Obj FuncCURRENT_STATEMENT_LOCATION(Obj self, Obj context) return retlist; } -static Obj FuncPRINT_CURRENT_STATEMENT(Obj self, Obj stream, Obj context, - Obj activeContext, Obj level, - Obj totalDepth) +static Obj FuncPRINT_CURRENT_STATEMENT(Obj self, + Obj stream, + Obj context, + Obj activeContext, + Obj level, + Obj prefixWidth) { + volatile Obj location = Fail; + if (IsBottomLVars(context)) - return 0; + return Fail; // HACK: we want to redirect output // Try to print the output to stream. Use *errout* as a fallback. @@ -208,35 +213,26 @@ static Obj FuncPRINT_CURRENT_STATEMENT(Obj self, Obj stream, Obj context, BOOL rethrow = FALSE; GAP_TRY { - UInt levelInt = INT_INTOBJ(level); - UInt totalDepthInt = INT_INTOBJ(totalDepth); - UInt prefixWidth = 0; - UInt levelWidth = 0; - UInt i; - - char prefix[32]; Obj func = FUNC_LVARS(context); Obj funcname = NAME_FUNC(func); Int line = -1; - GAP_ASSERT(func); + Stat call = STAT_LVARS(context); Obj body = BODY_FUNC(func); Obj filename = GET_FILENAME_BODY(body); - while (totalDepthInt > 0) { - prefixWidth++; - totalDepthInt /= 10; - } - if (activeContext != Fail) { - i = levelInt; + char prefix[32]; + UInt levelInt = INT_INTOBJ(level); + UInt levelWidth = 0; + UInt i = levelInt; while (i > 0) { levelWidth++; i /= 10; } snprintf(prefix, sizeof(prefix), "%c%*s[%lu] ", context == activeContext ? '*' : ' ', - (int)(prefixWidth - levelWidth), "", + (int)(INT_INTOBJ(prefixWidth) - levelWidth), "", (unsigned long)levelInt); Pr("%s", (Int)prefix, 0); } @@ -274,11 +270,7 @@ static Obj FuncPRINT_CURRENT_STATEMENT(Obj self, Obj stream, Obj context, SWITCH_TO_OLD_LVARS(currLVars); } if (line > 0) { - Pr("\n", 0, 0); - for (i = 0; i < prefixWidth + 2; i++) { - Pr(" ", 0, 0); - } - Pr("@ %g:%d", (Int)filename, line); + location = NewPlistFromArgs(filename, INTOBJ_INT(line)); } } GAP_CATCH @@ -292,7 +284,7 @@ static Obj FuncPRINT_CURRENT_STATEMENT(Obj self, Obj stream, Obj context, if (rethrow) GAP_THROW(); - return 0; + return location; } /**************************************************************************** diff --git a/tst/testinstall/kernel/gap.tst b/tst/testinstall/kernel/gap.tst index 493afea431..ba82a4c3ca 100644 --- a/tst/testinstall/kernel/gap.tst +++ b/tst/testinstall/kernel/gap.tst @@ -112,9 +112,9 @@ fail gap> CURRENT_STATEMENT_LOCATION(GetCurrentLVars()); fail gap> PRINT_CURRENT_STATEMENT("*errout*", GetCurrentLVars(), fail, 1, 1); +fail gap> f:=function() local l; l:=GetCurrentLVars(); PRINT_CURRENT_STATEMENT("*errout*", l, fail, 1, 1); Print("\n"); end;; f(); PRINT_CURRENT_STATEMENT( "*errout*", l, fail, 1, 1 ); - @ stream:1 # gap> CALL_WITH_CATCH(fail,fail); From 4e09c0807e0e79f28f569c8913e1a2e63b8d9669 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 9 Jun 2026 01:07:41 +0200 Subject: [PATCH 032/114] Adjust when 'Stack trace:' message is printed (#6432) * Adjust when 'Stack trace:' message is printed * Update one more error message * Add two missing 'Stack trace:' --- doc/ref/debug.xml | 6 +++- doc/ref/language.xml | 1 - doc/ref/mloop.xml | 35 ++++++++++--------- doc/ref/types.xml | 1 - doc/tut/group.xml | 1 + doc/tut/lists.xml | 1 - doc/tut/migrat.xml | 31 ++++++++-------- lib/error.g | 4 +-- lib/integer.gd | 1 + lib/oper1.g | 1 + .../64bit/low-mem-list-types.g.out | 3 -- tst/testspecial/64bit/low-mem-plist-1.g.out | 2 -- tst/testspecial/64bit/low-mem-plist-2.g.out | 2 -- tst/testspecial/backtrace.g.out | 30 ++++++++++++++++ tst/testspecial/backtrace2.g.out | 21 +++++++++++ tst/testspecial/debug-var.g.out | 1 - .../error-in-InputTextString.g.out | 1 - tst/testspecial/last-access.g.out | 1 - tst/testspecial/line-continuation.g.out | 2 -- tst/testspecial/method-not-found-where.g.out | 1 + tst/testspecial/print-formatting.g.out | 1 - tst/testspecial/repl-syntax-err.g.out | 1 - tst/testspecial/stack-trace-depth.g.out | 2 ++ tst/testspecial/top-level-error.g.out | 1 - tst/testspecial/trace.g.out | 6 ---- tst/testspecial/up-down-env.g.out | 2 -- 26 files changed, 98 insertions(+), 61 deletions(-) diff --git a/doc/ref/debug.xml b/doc/ref/debug.xml index e947af8d05..92f55cff95 100644 --- a/doc/ref/debug.xml +++ b/doc/ref/debug.xml @@ -42,7 +42,6 @@ error as in the following example occurs and a break loop is entered: gap> IsNormal(2,2); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `IsNormal' on 2 arguments -Stack trace: called from read-eval loop at *stdin*:1 type 'quit;' to quit to outer loop brk> @@ -918,6 +917,7 @@ gap> dive(100); gap> OnBreak:= function() Where(2); end;; # shorter traceback gap> dive(6000); Error, recursion depth trap (5000) +Stack trace: *[1] dive( depth - 1 ); @ *stdin*:1 [2] dive( depth - 1 ); @@ -928,6 +928,7 @@ you can 'return;' to continue brk> return; gap> dive(11000); Error, recursion depth trap (5000) +Stack trace: *[1] dive( depth - 1 ); @ *stdin*:1 [2] dive( depth - 1 ); @@ -937,6 +938,7 @@ you can 'quit;' to quit to outer loop, or you can 'return;' to continue brk> return; Error, recursion depth trap (10000) +Stack trace: *[1] dive( depth - 1 ); @ *stdin*:1 [2] dive( depth - 1 ); @@ -980,6 +982,7 @@ gap> dive(100); Depth 100 gap> dive(2500); Error, recursion depth trap (1000) +Stack trace: *[1] dive( depth - 1 ); @ *stdin*:4 [2] dive( depth - 1 ); @@ -989,6 +992,7 @@ you can 'quit;' to quit to outer loop, or you can 'return;' to continue brk> return; Error, recursion depth trap (2000) +Stack trace: *[1] dive( depth - 1 ); @ *stdin*:4 [2] dive( depth - 1 ); diff --git a/doc/ref/language.xml b/doc/ref/language.xml index cce1a2fbfc..b4fbfefcaa 100644 --- a/doc/ref/language.xml +++ b/doc/ref/language.xml @@ -716,7 +716,6 @@ gap> xx := 15; gap> MakeReadOnlyGlobal("xx"); gap> xx := 16; Error, Variable: 'xx' is read only -Stack trace: not in any function at *stdin*:3 type 'quit;' to quit to outer loop brk> quit; diff --git a/doc/ref/mloop.xml b/doc/ref/mloop.xml index ee80492a0b..a13c30e6c8 100644 --- a/doc/ref/mloop.xml +++ b/doc/ref/mloop.xml @@ -477,7 +477,6 @@ indicate that you are in a break loop. 1/0; Error, Rational operations: must not be zero -Stack trace: not in any function at *stdin*:2 type 'quit;' to quit to outer loop ]]> @@ -488,7 +487,6 @@ If errors occur within a break loop &GAP; enters another break loop at a 1/0; Error, Rational operations: must not be zero -Stack trace: not in any function at *errin*:1 type 'quit;' to quit to outer loop brk_2> @@ -634,7 +632,8 @@ Here is a somewhat trivial demonstration of the use of

ErrorNoTraceBack("Gidday!", " How's", " it", " going?\n"); -Error, Gidday! How's it going? +Error, +Gidday! How's it going? you can 'quit;' to quit to outer loop, or you can 'return;' to continue brk> quit; @@ -752,7 +751,8 @@ Error, user interrupt @ GAPROOT/lib/stbc.gi:18 ( ) called from read-eval loop at *stdin*:2 -you can 'return;' +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue brk> Where(2); *[1] genlabels := Filtered( genlabels, function ( x ) return pnt ^ sgs[x] = pnt; @@ -828,14 +828,15 @@ Error, ! you can 'quit;' to quit to outer loop, or you can 'return;' to continue brk> Where(); +Stack trace: *[1] Error( "!\n" ); - @ *stdin*:4 + @ *stdin*:3 [2] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [3] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [4] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 ( ) called from read-eval loop at *errin*:1 brk> n; @@ -844,28 +845,30 @@ brk> DownEnv(); brk> n; 3 brk> Where(); +Stack trace: [1] Error( "!\n" ); - @ *stdin*:4 + @ *stdin*:3 *[2] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [3] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [4] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 ( ) called from read-eval loop at *errin*:5 brk> DownEnv( 2 ); brk> n; 1 brk> Where(); +Stack trace: [1] Error( "!\n" ); - @ *stdin*:4 + @ *stdin*:3 [2] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [3] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 *[4] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 ( ) called from read-eval loop at *errin*:8 brk> DownEnv( -2 ); diff --git a/doc/ref/types.xml b/doc/ref/types.xml index b35730b539..cc80d788a6 100644 --- a/doc/ref/types.xml +++ b/doc/ref/types.xml @@ -602,7 +602,6 @@ for an object. Setter( prop )( Rationals, false ); Error, You cannot set an "and-filter" except to true -Stack trace: not in any function at *stdin*:8 type 'quit;' to quit to outer loop brk> diff --git a/doc/tut/group.xml b/doc/tut/group.xml index 3d19ea2713..f8b1020368 100644 --- a/doc/tut/group.xml +++ b/doc/tut/group.xml @@ -928,6 +928,7 @@ gap> Size( Image( hom, DerivedSubgroup(s4) ) ); PreImage( hom, (1,2,3) ); Error, must be an injective and surjective mapping +Stack trace: *[1] ErrorNoReturn( " must be an injective and surjective ", "mapping" ); @ GAPROOT/lib/mapping.gi:262 ( ) diff --git a/doc/tut/lists.xml b/doc/tut/lists.xml index de893722ef..0361f480bb 100644 --- a/doc/tut/lists.xml +++ b/doc/tut/lists.xml @@ -342,7 +342,6 @@ gap> list[3][5] := 'w';; list; copy; [ 1, 2, "three", [ 4 ] ] gap> copy[3][5] := 'w'; Error, List Assignment: must be a mutable list -Stack trace: not in any function at *stdin*:3 type 'quit;' to quit to outer loop brk> quit; diff --git a/doc/tut/migrat.xml b/doc/tut/migrat.xml index bf73228ae0..13cdad7898 100644 --- a/doc/tut/migrat.xml +++ b/doc/tut/migrat.xml @@ -851,24 +851,23 @@ When interrupting, the first line printed by Where actually may be one level higher, as shown below.

OnBreak := function() Where(0); end;; # eliminate back-tracing on -gap> # entry to break loop +gap> OnBreak := function() end;; # eliminate back-tracing on entry to break loop gap> test:= function( n ) > if n > 3 then Error( "!\n" ); fi; test( n+1 ); end;; gap> test( 1 ); Error, ! -at *stdin*:6 you can 'quit;' to quit to outer loop, or you can 'return;' to continue brk> Where(); +Stack trace: *[1] Error( "!\n" ); - @ *stdin*:4 + @ *stdin*:3 [2] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [3] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [4] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 ( ) called from read-eval loop at *errin*:1 brk> n; @@ -877,28 +876,30 @@ brk> DownEnv(); brk> n; 3 brk> Where(); +Stack trace: [1] Error( "!\n" ); - @ *stdin*:4 + @ *stdin*:3 *[2] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [3] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [4] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 ( ) called from read-eval loop at *errin*:5 brk> DownEnv( 2 ); brk> n; 1 brk> Where(); +Stack trace: [1] Error( "!\n" ); - @ *stdin*:4 + @ *stdin*:3 [2] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [3] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 *[4] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 ( ) called from read-eval loop at *errin*:8 brk> DownEnv( -2 ); diff --git a/lib/error.g b/lib/error.g index 2a942b4fec..0daa77277a 100644 --- a/lib/error.g +++ b/lib/error.g @@ -145,6 +145,7 @@ BIND_GLOBAL("WHERE", function(depth, context, activecontext, showlocals) PrintTo(ERROR_OUTPUT, "called from read-eval loop "); return; fi; + PrintTo(ERROR_OUTPUT, "Stack trace:\n"); lastcontext := context; totaldepth := 0; countcontext := context; @@ -308,9 +309,6 @@ BIND_GLOBAL("ErrorInner", function(options, earlyMessage) printAutomaticTraceback := function() if IsBound(OnBreak) and IsFunction(OnBreak) then - if OnBreak = Where or OnBreak = WhereWithVars then - PrintTo(ERROR_OUTPUT, "Stack trace:\n"); - fi; OnBreak(); fi; end; diff --git a/lib/integer.gd b/lib/integer.gd index 20ca4e07ed..c2ae9c8ac8 100644 --- a/lib/integer.gd +++ b/lib/integer.gd @@ -249,6 +249,7 @@ DeclareGlobalFunction( "BestQuoInt" ); ## ChineseRem( [ 6, 10, 14 ], [ 1, 2, 3 ] ); ## Error, the residues must be equal modulo 2 +## Stack trace: ## *[1] Error( "the residues must be equal modulo ", g.gcd ); ## @ GAPROOT/lib/integer.gi:391 ## ( ) diff --git a/lib/oper1.g b/lib/oper1.g index 2c25bf1cff..1abc10d131 100644 --- a/lib/oper1.g +++ b/lib/oper1.g @@ -929,6 +929,7 @@ end); ## SylowSubgroup( s4, 6 ); ## Error, SylowSubgroup:

must be a prime +## Stack trace: ## *[1] <> ## @ GAPROOT/lib/oper1.g:964 ## [2] <> diff --git a/tst/testspecial/64bit/low-mem-list-types.g.out b/tst/testspecial/64bit/low-mem-list-types.g.out index 086225b90a..b8c7f74302 100644 --- a/tst/testspecial/64bit/low-mem-list-types.g.out +++ b/tst/testspecial/64bit/low-mem-list-types.g.out @@ -1,18 +1,15 @@ gap> ListWithIdenticalEntries(2^50, 'a'); Error, Cannot allocate 1125899906842633 bytes: cannot extend the workspace any more!! -Stack trace: not in any function at *stdin*:2 type 'quit;' to quit to outer loop brk> quit; gap> ListWithIdenticalEntries(2^50, true); Error, Cannot allocate 140737488355336 bytes: cannot extend the workspace any more!! -Stack trace: not in any function at *stdin*:2 type 'quit;' to quit to outer loop brk> quit; gap> ListWithIdenticalEntries(2^50, 2); Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!! -Stack trace: not in any function at *stdin*:2 type 'quit;' to quit to outer loop brk> quit; diff --git a/tst/testspecial/64bit/low-mem-plist-1.g.out b/tst/testspecial/64bit/low-mem-plist-1.g.out index 9264df9d43..f3bdaee9b0 100644 --- a/tst/testspecial/64bit/low-mem-plist-1.g.out +++ b/tst/testspecial/64bit/low-mem-plist-1.g.out @@ -2,13 +2,11 @@ gap> l := []; [ ] gap> l[2^50] := 1; Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!!!! -Stack trace: not in any function at *stdin*:3 type 'quit;' to quit to outer loop brk> quit; gap> l[2^50] := 2; Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!!!! -Stack trace: not in any function at *stdin*:3 type 'quit;' to quit to outer loop brk> quit; diff --git a/tst/testspecial/64bit/low-mem-plist-2.g.out b/tst/testspecial/64bit/low-mem-plist-2.g.out index d50a3a7ab5..3d430e5bb8 100644 --- a/tst/testspecial/64bit/low-mem-plist-2.g.out +++ b/tst/testspecial/64bit/low-mem-plist-2.g.out @@ -1,12 +1,10 @@ gap> EmptyPlist(2^50); Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!! -Stack trace: not in any function at *stdin*:2 type 'quit;' to quit to outer loop brk> quit; gap> EmptyPlist(2^50); Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!! -Stack trace: not in any function at *stdin*:2 type 'quit;' to quit to outer loop brk> quit; diff --git a/tst/testspecial/backtrace.g.out b/tst/testspecial/backtrace.g.out index f2130d7a95..c29cadf6fc 100644 --- a/tst/testspecial/backtrace.g.out +++ b/tst/testspecial/backtrace.g.out @@ -20,11 +20,13 @@ Stack trace: called from read-eval loop at *stdin*:13 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] l[[ 1 .. 3 ]] := 1; @ *stdin*:11 ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] l[[ 1 .. 3 ]] := 1; @ *stdin*:11 arguments: @@ -45,11 +47,13 @@ Stack trace: called from read-eval loop at *stdin*:16 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] 1 / 0 @ *stdin*:15 ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] 1 / 0 @ *stdin*:15 arguments: @@ -71,6 +75,7 @@ fi; called from read-eval loop at *stdin*:19 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] if x then return 1; fi; @@ -78,6 +83,7 @@ fi; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] if x then return 1; fi; @@ -102,6 +108,7 @@ fi; called from read-eval loop at *stdin*:22 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] if 1 then return 1; fi; @@ -109,6 +116,7 @@ fi; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] if 1 then return 1; fi; @@ -134,6 +142,7 @@ fi; called from read-eval loop at *stdin*:25 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] if 1 < 0 then return 1; elif 1 then @@ -143,6 +152,7 @@ fi; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] if 1 < 0 then return 1; elif 1 then @@ -168,6 +178,7 @@ od; called from read-eval loop at *stdin*:28 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] while 1 do return 1; od; @@ -175,6 +186,7 @@ od; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] while 1 do return 1; od; @@ -201,6 +213,7 @@ od; you can 'quit;' to quit to outer loop, or you can 'return;' to continue brk> Where(); +Stack trace: *[1] Error( "You cannot loop over the integer ", n, " did you mean the range [1..", n, "]" ); @ GAPROOT/lib/integer.gi:LINE [2] for i in 1 do @@ -210,6 +223,7 @@ od; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] Error( "You cannot loop over the integer ", n, " did you mean the range [1..", n, "]" ); @ GAPROOT/lib/integer.gi:LINE arguments: @@ -240,6 +254,7 @@ od; called from read-eval loop at *stdin*:34 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] for i in true do return 1; od; @@ -247,6 +262,7 @@ od; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] for i in true do return 1; od; @@ -271,6 +287,7 @@ od; called from read-eval loop at *stdin*:36 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] for i in true do return 1; od; @@ -278,6 +295,7 @@ od; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] for i in true do return 1; od; @@ -304,6 +322,7 @@ od; called from read-eval loop at *stdin*:38 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] for i in true do return 1; od; @@ -311,6 +330,7 @@ od; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] for i in true do return 1; od; @@ -337,6 +357,7 @@ od; called from read-eval loop at *stdin*:40 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] for i in true do return 1; od; @@ -344,6 +365,7 @@ od; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] for i in true do return 1; od; @@ -369,6 +391,7 @@ until 1; called from read-eval loop at *stdin*:42 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] repeat x := 1; until 1; @@ -376,6 +399,7 @@ until 1; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] repeat x := 1; until 1; @@ -398,11 +422,13 @@ Stack trace: called from read-eval loop at *stdin*:45 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] Assert( 0, 1 ); @ *stdin*:44 ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] Assert( 0, 1 ); @ *stdin*:44 arguments: @@ -423,11 +449,13 @@ Stack trace: called from read-eval loop at *stdin*:48 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] Assert( 0, 1, "hello" ); @ *stdin*:47 ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] Assert( 0, 1, "hello" ); @ *stdin*:47 arguments: @@ -457,6 +485,7 @@ Stack trace: called from read-eval loop at *stdin*:56 type 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] return m[i][j]; @ GAPROOT/lib/matrix.gi:LINE [2] ELM_LIST( m, row, col ) @@ -466,6 +495,7 @@ brk> Where(); ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] return m[i][j]; @ GAPROOT/lib/matrix.gi:LINE arguments: diff --git a/tst/testspecial/backtrace2.g.out b/tst/testspecial/backtrace2.g.out index 3583cc7588..51ade71f0c 100644 --- a/tst/testspecial/backtrace2.g.out +++ b/tst/testspecial/backtrace2.g.out @@ -39,6 +39,7 @@ you can 'quit;' to quit to outer loop, or you can 'return;' to continue brk> n; Where(); 3 +Stack trace: *[1] Error( "!\n" ); @ *stdin*:24 [2] test( n + 1 ); @@ -49,6 +50,7 @@ brk> n; Where(); called from read-eval loop at *errin*:1 brk> DownEnv(); n; Where(); 2 +Stack trace: [1] Error( "!\n" ); @ *stdin*:24 *[2] test( n + 1 ); @@ -59,6 +61,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:2 brk> DownEnv(); n; Where(); 1 +Stack trace: [1] Error( "!\n" ); @ *stdin*:24 [2] test( n + 1 ); @@ -69,6 +72,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:3 brk> DownEnv(); n; Where(); 1 +Stack trace: [1] Error( "!\n" ); @ *stdin*:24 [2] test( n + 1 ); @@ -79,6 +83,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:4 brk> UpEnv(); n; Where(); 2 +Stack trace: [1] Error( "!\n" ); @ *stdin*:24 *[2] test( n + 1 ); @@ -89,6 +94,7 @@ brk> UpEnv(); n; Where(); called from read-eval loop at *errin*:5 brk> UpEnv(); n; Where(); 3 +Stack trace: *[1] Error( "!\n" ); @ *stdin*:24 [2] test( n + 1 ); @@ -99,6 +105,7 @@ brk> UpEnv(); n; Where(); called from read-eval loop at *errin*:6 brk> UpEnv(); n; Where(); 3 +Stack trace: *[1] Error( "!\n" ); @ *stdin*:24 [2] test( n + 1 ); @@ -133,6 +140,7 @@ Stack trace: type 'quit;' to quit to outer loop brk> n; Where(); 3 +Stack trace: *[1] 1 / 0 @ *stdin*:35 [2] test( n + 1 ); @@ -143,6 +151,7 @@ brk> n; Where(); called from read-eval loop at *errin*:1 brk> DownEnv(); n; Where(); 2 +Stack trace: [1] 1 / 0 @ *stdin*:35 *[2] test( n + 1 ); @@ -153,6 +162,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:2 brk> DownEnv(); n; Where(); 1 +Stack trace: [1] 1 / 0 @ *stdin*:35 [2] test( n + 1 ); @@ -163,6 +173,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:3 brk> DownEnv(); n; Where(); 1 +Stack trace: [1] 1 / 0 @ *stdin*:35 [2] test( n + 1 ); @@ -173,6 +184,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:4 brk> UpEnv(); n; Where(); 2 +Stack trace: [1] 1 / 0 @ *stdin*:35 *[2] test( n + 1 ); @@ -183,6 +195,7 @@ brk> UpEnv(); n; Where(); called from read-eval loop at *errin*:5 brk> UpEnv(); n; Where(); 3 +Stack trace: *[1] 1 / 0 @ *stdin*:35 [2] test( n + 1 ); @@ -193,6 +206,7 @@ brk> UpEnv(); n; Where(); called from read-eval loop at *errin*:6 brk> UpEnv(); n; Where(); 3 +Stack trace: *[1] 1 / 0 @ *stdin*:35 [2] test( n + 1 ); @@ -229,6 +243,7 @@ Stack trace: type 'quit;' to quit to outer loop brk> n; Where(); 3 +Stack trace: *[1] IsAbelian( 1 ) @ *stdin*:47 [2] test( n + 1 ); @@ -239,6 +254,7 @@ brk> n; Where(); called from read-eval loop at *errin*:1 brk> DownEnv(); n; Where(); 3 +Stack trace: *[1] IsAbelian( 1 ) @ *stdin*:47 [2] test( n + 1 ); @@ -249,6 +265,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:2 brk> DownEnv(); n; Where(); 2 +Stack trace: [1] IsAbelian( 1 ) @ *stdin*:47 *[2] test( n + 1 ); @@ -259,6 +276,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:3 brk> DownEnv(); n; Where(); 1 +Stack trace: [1] IsAbelian( 1 ) @ *stdin*:47 [2] test( n + 1 ); @@ -269,6 +287,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:4 brk> UpEnv(); n; Where(); 2 +Stack trace: [1] IsAbelian( 1 ) @ *stdin*:47 *[2] test( n + 1 ); @@ -279,6 +298,7 @@ brk> UpEnv(); n; Where(); called from read-eval loop at *errin*:5 brk> UpEnv(); n; Where(); 3 +Stack trace: *[1] IsAbelian( 1 ) @ *stdin*:47 [2] test( n + 1 ); @@ -289,6 +309,7 @@ brk> UpEnv(); n; Where(); called from read-eval loop at *errin*:6 brk> UpEnv(); n; Where(); 3 +Stack trace: *[1] IsAbelian( 1 ) @ *stdin*:47 [2] test( n + 1 ); diff --git a/tst/testspecial/debug-var.g.out b/tst/testspecial/debug-var.g.out index c39af18014..ab72b2459f 100644 --- a/tst/testspecial/debug-var.g.out +++ b/tst/testspecial/debug-var.g.out @@ -89,7 +89,6 @@ gap> x; 42 gap> y; Error, Variable: 'y' must have a value -Stack trace: not in any function at *stdin*:16 gap> gap> h:=function(p) diff --git a/tst/testspecial/error-in-InputTextString.g.out b/tst/testspecial/error-in-InputTextString.g.out index 18aca9b5f0..36b19d8b23 100644 --- a/tst/testspecial/error-in-InputTextString.g.out +++ b/tst/testspecial/error-in-InputTextString.g.out @@ -1,7 +1,6 @@ gap> Read(InputTextString("Print(1 + [()]);")); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `+' on 2 arguments -Stack trace: called from read-eval loop at stream:1 type 'quit;' to quit to outer loop brk> quit; diff --git a/tst/testspecial/last-access.g.out b/tst/testspecial/last-access.g.out index d958151341..78d756615f 100644 --- a/tst/testspecial/last-access.g.out +++ b/tst/testspecial/last-access.g.out @@ -5,7 +5,6 @@ gap> 1;2;3;[last,last2,last3]; [ 3, 2, 1 ] gap> Error("err"); Error, err -Stack trace: not in any function at *stdin*:3 you can 'quit;' to quit to outer loop, or you can 'return;' to continue diff --git a/tst/testspecial/line-continuation.g.out b/tst/testspecial/line-continuation.g.out index 88f253686c..2f06f33fdc 100644 --- a/tst/testspecial/line-continuation.g.out +++ b/tst/testspecial/line-continuation.g.out @@ -4,7 +4,6 @@ gap> # counter only once, so that both examples below report the error in line 2 gap> # gap> EvalString("123\\\n45x;"); Error, Variable: '12345x' must have a value -Stack trace: not in any function at stream:2 Error, Could not evaluate string. Stack trace: @@ -17,7 +16,6 @@ you can 'return;' to continue brk> quit; gap> EvalString("123\\\r\n45x;"); Error, Variable: '12345x' must have a value -Stack trace: not in any function at stream:2 Error, Could not evaluate string. Stack trace: diff --git a/tst/testspecial/method-not-found-where.g.out b/tst/testspecial/method-not-found-where.g.out index 30601cd166..eaaeaee161 100644 --- a/tst/testspecial/method-not-found-where.g.out +++ b/tst/testspecial/method-not-found-where.g.out @@ -13,6 +13,7 @@ brk> ShowMethods(1); #I Searching Method for IsDiagonalMatrix with 1 argument: #I Total: 3 entries brk> Where(5); +Stack trace: *[1] IsDiagonalMat( a ) @ *stdin*:3 ( ) diff --git a/tst/testspecial/print-formatting.g.out b/tst/testspecial/print-formatting.g.out index 984e623ac8..91e7af8741 100644 --- a/tst/testspecial/print-formatting.g.out +++ b/tst/testspecial/print-formatting.g.out @@ -22,7 +22,6 @@ gap> gap> # test formatting status for errout gap> 1/0; # trigger a break loop Error, Rational operations: must not be zero -Stack trace: not in any function at *stdin*:14 type 'quit;' to quit to outer loop brk> old := PrintFormattingStatus("*errout*"); diff --git a/tst/testspecial/repl-syntax-err.g.out b/tst/testspecial/repl-syntax-err.g.out index 9b4f6bc090..7f31dd0233 100644 --- a/tst/testspecial/repl-syntax-err.g.out +++ b/tst/testspecial/repl-syntax-err.g.out @@ -7,7 +7,6 @@ gap> # error, which wasn't reported correctly before the above issues was gap> # fixed. gap> Error(""): Error, -Stack trace: not in any function at *stdin*:9 you can 'quit;' to quit to outer loop, or you can 'return;' to continue diff --git a/tst/testspecial/stack-trace-depth.g.out b/tst/testspecial/stack-trace-depth.g.out index 7a30baca80..9c12a52a9a 100644 --- a/tst/testspecial/stack-trace-depth.g.out +++ b/tst/testspecial/stack-trace-depth.g.out @@ -49,6 +49,7 @@ you can 'quit;' to quit to outer loop, or you can 'return;' to continue brk> SetUserPreference("WhereDepth", 12); brk> Where(); +Stack trace: * [1] Error( "foo" ); @ *stdin*:3 [2] f11( ) @@ -75,6 +76,7 @@ brk> Where(); called from read-eval loop at *errin*:2 brk> SetUserPreference("WhereDepth", 5); brk> Where(); +Stack trace: *[1] Error( "foo" ); @ *stdin*:3 [2] f11( ) diff --git a/tst/testspecial/top-level-error.g.out b/tst/testspecial/top-level-error.g.out index 9ed8d6c077..f27f9df6d9 100644 --- a/tst/testspecial/top-level-error.g.out +++ b/tst/testspecial/top-level-error.g.out @@ -1,6 +1,5 @@ gap> Error("foo"); Error, foo -Stack trace: not in any function at *stdin*:2 you can 'quit;' to quit to outer loop, or you can 'return;' to continue diff --git a/tst/testspecial/trace.g.out b/tst/testspecial/trace.g.out index 3467715778..844962b4d0 100644 --- a/tst/testspecial/trace.g.out +++ b/tst/testspecial/trace.g.out @@ -31,7 +31,6 @@ gap> o(1,2,3,4,5,6); [ 1, 2, 3, 4, 5, 6 ] gap> o(1,2,3,4,5,6,7); # not (yet?) supported Error, sorry: cannot yet have X argument operations -Stack trace: not in any function at *stdin*:25 gap> gap> # with tracing @@ -59,7 +58,6 @@ gap> o(1,2,3,4,5,6); [ 1, 2, 3, 4, 5, 6 ] gap> o(1,2,3,4,5,6,7); Error, sorry: cannot yet have X argument operations -Stack trace: not in any function at *stdin*:36 gap> UntraceMethods( o ); # not (yet?) supported gap> @@ -80,7 +78,6 @@ gap> o(1,2,3,4,5,6); [ 1, 2, 3, 4, 5, 6 ] gap> o(1,2,3,4,5,6,7); # not (yet?) supported Error, sorry: cannot yet have X argument operations -Stack trace: not in any function at *stdin*:47 gap> gap> # @@ -113,7 +110,6 @@ gap> o(IsInt,2,3,4,5,6); [ , 2, 3, 4, 5, 6 ] gap> o(IsInt,2,3,4,5,6,7); # not (yet?) supported Error, sorry: cannot yet have X argument constructors -Stack trace: not in any function at *stdin*:70 gap> gap> # with tracing @@ -138,7 +134,6 @@ gap> o(IsInt,2,3,4,5,6); [ , 2, 3, 4, 5, 6 ] gap> o(IsInt,2,3,4,5,6,7); # not (yet?) supported Error, sorry: cannot yet have X argument constructors -Stack trace: not in any function at *stdin*:80 gap> UntraceMethods( o ); gap> @@ -157,6 +152,5 @@ gap> o(IsInt,2,3,4,5,6); [ , 2, 3, 4, 5, 6 ] gap> o(IsInt,2,3,4,5,6,7); # not (yet?) supported Error, sorry: cannot yet have X argument constructors -Stack trace: not in any function at *stdin*:90 gap> QUIT; diff --git a/tst/testspecial/up-down-env.g.out b/tst/testspecial/up-down-env.g.out index f27012aa67..93062e655b 100644 --- a/tst/testspecial/up-down-env.g.out +++ b/tst/testspecial/up-down-env.g.out @@ -55,7 +55,6 @@ brk> ## start a fresh execution context brk> ## brk> Read("top-level-error.g"); Error, foo -Stack trace: not in any function at top-level-error.g:1 you can 'quit;' to quit to outer loop, or you can 'return;' to continue @@ -63,7 +62,6 @@ brk_2> Where(20); not in any function at *errin*:1 brk_2> lvl; # since `Read` started a fresh execution context, we can't access lvl here Error, Variable: 'lvl' must have a value -Stack trace: not in any function at *errin*:2 brk_2> quit; brk> lvl; From a1246781ed9e7b3453ae6dc261eaf38cc850fa8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 01:14:45 +0200 Subject: [PATCH 033/114] build(deps): bump codecov/codecov-action from 6 to 7 (#6430) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 6 to 7. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v6...v7) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 0159bdcfb8..e9937fed7f 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -276,7 +276,7 @@ jobs: - name: "Gather coverage data" run: ${{ matrix.extra }} dev/ci-gather-coverage.sh - name: "Upload coverage data to Codecov" - uses: codecov/codecov-action@v6 + uses: codecov/codecov-action@v7 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -288,7 +288,7 @@ jobs: steps: - name: "Send Codecov notifications" - uses: codecov/codecov-action@v6 + uses: codecov/codecov-action@v7 with: token: ${{ secrets.CODECOV_TOKEN }} run_command: send-notifications From ba5ed0cf8b8f05b28a24da8f85fdbd609eaa9b0d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 9 Jun 2026 02:38:24 +0200 Subject: [PATCH 034/114] Adjust conway polynomial error message (#6433) The 'return to continue' is redundant and potentially confusing. --- hpcgap/lib/ffeconway.gi | 2 +- lib/ffe.gd | 6 +++--- lib/ffeconway.gi | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hpcgap/lib/ffeconway.gi b/hpcgap/lib/ffeconway.gi index ff9d82145e..d148ad64f5 100644 --- a/hpcgap/lib/ffeconway.gi +++ b/hpcgap/lib/ffeconway.gi @@ -80,7 +80,7 @@ FFECONWAY.SetUpConwayStuff := function(p,d) if not IsCheapConwayPolynomial(p,d) then Error("Conway Polynomial ",p,"^",d, - " will need to computed and might be slow\n", "return to continue"); + " will need to be computed and might be slow"); fi; cp := CoefficientsOfUnivariatePolynomial(ConwayPolynomial(p,d)); diff --git a/lib/ffe.gd b/lib/ffe.gd index 3eeddef057..1bd089717a 100644 --- a/lib/ffe.gd +++ b/lib/ffe.gd @@ -118,9 +118,9 @@ ## ]]> ## Z(11,40); -## Error, Conway Polynomial 11^40 will need to computed and might be slow -## return to continue -## *[1] Error( "Conway Polynomial ", p, "^", d, " will need to computed and might be slow\n", "return to continue" ); +## Error, Conway Polynomial 11^40 will need to be computed and might be slow +## Stack trace: +## *[1] Error( "Conway Polynomial ", p, "^", d, " will need to be computed and might be slow" ); ## @ GAPROOT/lib/ffeconway.gi:81 ## [2] FFECONWAY.SetUpConwayStuff( p, d ); ## @ GAPROOT/lib/ffeconway.gi:140 diff --git a/lib/ffeconway.gi b/lib/ffeconway.gi index fd6f5b721d..04555686d4 100644 --- a/lib/ffeconway.gi +++ b/lib/ffeconway.gi @@ -78,7 +78,7 @@ FFECONWAY.SetUpConwayStuff := function(p,d) if not IsCheapConwayPolynomial(p,d) then Error("Conway Polynomial ",p,"^",d, - " will need to computed and might be slow\n", "return to continue"); + " will need to be computed and might be slow"); fi; cp := CoefficientsOfUnivariatePolynomial(ConwayPolynomial(p,d)); From 5dcc98eb8ea46ea8fd9e8cdecf507c4a0084a5e0 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 9 Jun 2026 02:43:58 +0200 Subject: [PATCH 035/114] Widen declaration for many matrix related functions (#6095) Also remove some now redundant methods. Before: gap> m:=RandomMat(256, 256, GF(1000000007));; gap> mat:=Matrix(IsZmodnZMatrixRep, GF(1000000007), m);; gap> RankMat(mat)=256; time; true 170 gap> DeterminantMat(mat); time; ZmodpZObj( 873487643, 1000000007 ) 23982 After: gap> m:=RandomMat(256, 256, GF(1000000007));; gap> mat:=Matrix(IsZmodnZMatrixRep, GF(1000000007), m);; gap> RankMat(mat)=256; time; true 161 gap> DeterminantMat(mat); time; ZmodpZObj( 873487643, 1000000007 ) 1949 --- lib/matobjnz.gi | 16 ------------ lib/matrix.gd | 68 ++++++++++++++++++++++++------------------------- lib/matrix.gi | 30 +++++++++++----------- 3 files changed, 49 insertions(+), 65 deletions(-) diff --git a/lib/matobjnz.gi b/lib/matobjnz.gi index c2edf17d3a..e2ac12cd69 100644 --- a/lib/matobjnz.gi +++ b/lib/matobjnz.gi @@ -1315,14 +1315,6 @@ InstallMethod( InverseSameMutability, "for a zmodnz matrix", return n; end ); -InstallMethod( RankMat, "for a zmodnz matrix", [ IsZmodnZMatrixRep ], -function( m ) - m:=MutableCopyMatrix(m); - m:=SemiEchelonMatDestructive(m); - if m<>fail then m:=Length(m.vectors);fi; - return m; -end); - #InstallMethodWithRandomSource( Randomize, # "for a random source and a mutable zmodnz matrix", @@ -1451,14 +1443,6 @@ InstallMethod( CompatibleVector, "for a zmodnz matrix", return NewZeroVector(IsZmodnZVectorRep,BaseDomain(v),NumberRows(v)); end ); -InstallMethod( DeterminantMat, "for a zmodnz matrix", [ IsZmodnZMatrixRep ], -function( a ) -local m; - m:=Size(BaseDomain(a)); - a:=List(a![ROWSPOS],x->x![ELSPOS]); - return ZmodnZObj(DeterminantMat(a),m); -end ); - # Minimal/Characteristic Polynomial stuff ############################################################################# diff --git a/lib/matrix.gd b/lib/matrix.gd index 4fe2262981..31ddbf47fb 100644 --- a/lib/matrix.gd +++ b/lib/matrix.gd @@ -296,7 +296,7 @@ DeclareSynonym( "DiagonalOfMat", DiagonalOfMatrix ); ## ## <#/GAPDoc> ## -DeclareAttribute( "BaseMat", IsMatrix ); +DeclareAttribute( "BaseMat", IsMatrixOrMatrixObj ); ############################################################################# ## @@ -323,7 +323,7 @@ DeclareAttribute( "BaseMat", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareOperation( "BaseMatDestructive", [ IsMatrix ] ); +DeclareOperation( "BaseMatDestructive", [ IsMatrixOrMatrixObj ] ); ############################################################################# ## @@ -345,7 +345,7 @@ DeclareOperation( "BaseMatDestructive", [ IsMatrix ] ); ## ## <#/GAPDoc> ## -DeclareAttribute( "BaseOrthogonalSpaceMat", IsMatrix ); +DeclareAttribute( "BaseOrthogonalSpaceMat", IsMatrixOrMatrixObj ); ############################################################################# @@ -372,7 +372,7 @@ DeclareAttribute( "BaseOrthogonalSpaceMat", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareAttribute( "DefaultFieldOfMatrix", IsMatrix ); +DeclareAttribute( "DefaultFieldOfMatrix", IsMatrixOrMatrixObj ); ############################################################################# @@ -396,7 +396,7 @@ DeclareAttribute( "DefaultFieldOfMatrix", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareAttribute( "DepthOfUpperTriangularMatrix", IsMatrix ); +DeclareAttribute( "DepthOfUpperTriangularMatrix", IsMatrixOrMatrixObj ); ############################################################################# @@ -503,7 +503,7 @@ DeclareSynonym( "DeterminantMatDivFree", DeterminantMatrixDivFree ); ## ## <#/GAPDoc> ## -DeclareAttribute( "DimensionsMat", IsMatrix ); +DeclareAttribute( "DimensionsMat", IsMatrixOrMatrixObj ); ############################################################################# @@ -550,7 +550,7 @@ DeclareAttribute( "DimensionsMat", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareOperation( "ElementaryDivisorsMat", [IsRing,IsMatrix] ); +DeclareOperation( "ElementaryDivisorsMat", [IsRing, IsMatrixOrMatrixObj] ); DeclareGlobalFunction( "ElementaryDivisorsMatDestructive" ); ############################################################################# @@ -623,7 +623,7 @@ DeclareGlobalFunction( "ElementaryDivisorsMatDestructive" ); ## ## <#/GAPDoc> ## -DeclareOperation( "ElementaryDivisorsTransformationsMat", [IsRing,IsMatrix] ); +DeclareOperation( "ElementaryDivisorsTransformationsMat", [IsRing, IsMatrixOrMatrixObj] ); DeclareGlobalFunction( "ElementaryDivisorsTransformationsMatDestructive" ); ############################################################################# @@ -640,7 +640,7 @@ DeclareGlobalFunction( "ElementaryDivisorsTransformationsMatDestructive" ); ## ## ## -DeclareOperation( "TriangulizedNullspaceMatNT", [ IsMatrix ] ); +DeclareOperation( "TriangulizedNullspaceMatNT", [ IsMatrixOrMatrixObj ] ); ############################################################################# @@ -666,8 +666,8 @@ DeclareOperation( "TriangulizedNullspaceMatNT", [ IsMatrix ] ); ## ## <#/GAPDoc> ## -DeclareAttribute( "NullspaceMat", IsMatrix ); -DeclareAttribute( "TriangulizedNullspaceMat", IsMatrix ); +DeclareAttribute( "NullspaceMat", IsMatrixOrMatrixObj ); +DeclareAttribute( "TriangulizedNullspaceMat", IsMatrixOrMatrixObj ); ############################################################################# @@ -706,8 +706,8 @@ DeclareAttribute( "TriangulizedNullspaceMat", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareOperation( "NullspaceMatDestructive", [ IsMatrix and IsMutable] ); -DeclareOperation( "TriangulizedNullspaceMatDestructive", [ IsMatrix and IsMutable] ); +DeclareOperation( "NullspaceMatDestructive", [ IsMatrixOrMatrixObj and IsMutable] ); +DeclareOperation( "TriangulizedNullspaceMatDestructive", [ IsMatrixOrMatrixObj and IsMutable] ); ############################################################################# @@ -779,7 +779,7 @@ DeclareOperation( "Eigenvalues", [ IsRing, IsMatrixOrMatrixObj ] ); ## ## <#/GAPDoc> ## -DeclareOperation( "Eigenspaces", [ IsRing, IsMatrix ] ); +DeclareOperation( "Eigenspaces", [ IsRing, IsMatrixOrMatrixObj ] ); ############################################################################# ## @@ -795,7 +795,7 @@ DeclareOperation( "Eigenspaces", [ IsRing, IsMatrix ] ); ## ## <#/GAPDoc> ## -DeclareOperation( "Eigenvectors", [ IsRing, IsMatrix ] ); +DeclareOperation( "Eigenvectors", [ IsRing, IsMatrixOrMatrixObj ] ); ############################################################################# @@ -926,7 +926,7 @@ DeclareSynonymAttr( "RankMatDestructive", RankMatrixDestructive ); ## ## <#/GAPDoc> ## -DeclareAttribute( "SemiEchelonMat", IsMatrix ); +DeclareAttribute( "SemiEchelonMat", IsMatrixOrMatrixObj ); ############################################################################# ## @@ -950,7 +950,7 @@ DeclareAttribute( "SemiEchelonMat", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareOperation( "SemiEchelonMatDestructive", [ IsMatrix and IsMutable] ); +DeclareOperation( "SemiEchelonMatDestructive", [ IsMatrixOrMatrixObj and IsMutable] ); ############################################################################# @@ -987,7 +987,7 @@ DeclareOperation( "SemiEchelonMatDestructive", [ IsMatrix and IsMutable] ); ## ## <#/GAPDoc> ## -DeclareAttribute( "SemiEchelonMatTransformation", IsMatrix ); +DeclareAttribute( "SemiEchelonMatTransformation", IsMatrixOrMatrixObj ); ############################################################################# ## @@ -1003,7 +1003,7 @@ DeclareAttribute( "SemiEchelonMatTransformation", IsMatrix ); ## ## DeclareOperation( "SemiEchelonMatTransformationDestructive", [ - IsMatrix and IsMutable ] ); + IsMatrixOrMatrixObj and IsMutable ] ); ############################################################################# @@ -1135,7 +1135,7 @@ DeclareSynonym( "MutableTransposedMat", TransposedMatMutable ); # needed? ## ## ## -DeclareOperation( "MutableTransposedMatDestructive", [IsMatrix and IsMutable] ); +DeclareOperation( "MutableTransposedMatDestructive", [IsMatrixOrMatrixObj and IsMutable] ); ############################################################################# @@ -1163,7 +1163,7 @@ DeclareOperation( "MutableTransposedMatDestructive", [IsMatrix and IsMutable] ); ## ## <#/GAPDoc> ## -DeclareOperation( "TransposedMatDestructive", [ IsMatrix ] ); +DeclareOperation( "TransposedMatDestructive", [ IsMatrixOrMatrixObj ] ); @@ -1186,7 +1186,7 @@ DeclareOperation( "TransposedMatDestructive", [ IsMatrix ] ); ## ## <#/GAPDoc> ## -DeclareProperty( "IsMonomialMatrix", IsMatrix ); +DeclareProperty( "IsMonomialMatrix", IsMatrixOrMatrixObj ); ############################################################################# @@ -1211,7 +1211,7 @@ DeclareProperty( "IsMonomialMatrix", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareOperation( "InverseMatMod", [ IsMatrix, IsObject ] ); +DeclareOperation( "InverseMatMod", [ IsMatrixOrMatrixObj, IsObject ] ); ############################################################################# @@ -1246,11 +1246,11 @@ DeclareOperation( "KroneckerProduct", [ IsMatrixOrMatrixObj, IsMatrixOrMatrixObj ## ## ## -## Does thework for SolutionMat and SolutionMatDestructive. +## Does the work for SolutionMat and SolutionMatDestructive. ## ## ## -DeclareOperation( "SolutionMatNoCo", [ IsMatrix, IsRowVector ] ); +DeclareOperation( "SolutionMatNoCo", [ IsMatrixOrMatrixObj, IsRowVectorOrVectorObj ] ); ############################################################################# @@ -1268,7 +1268,7 @@ DeclareOperation( "SolutionMatNoCo", [ IsMatrix, IsRowVector ] ); ## ## <#/GAPDoc> ## -DeclareOperation( "SolutionMat", [ IsMatrix, IsRowVector ] ); +DeclareOperation( "SolutionMat", [ IsMatrixOrMatrixObj, IsRowVectorOrVectorObj ] ); ############################################################################# ## @@ -1300,7 +1300,7 @@ DeclareOperation( "SolutionMat", [ IsMatrix, IsRowVector ] ); ## <#/GAPDoc> ## DeclareOperation( "SolutionMatDestructive", - [ IsMatrix and IsMutable, IsRowVector ] ); + [ IsMatrixOrMatrixObj and IsMutable, IsRowVectorOrVectorObj ] ); ############################################################################ @@ -1326,7 +1326,7 @@ DeclareOperation( "SolutionMatDestructive", ## ## <#/GAPDoc> ## -DeclareOperation( "SumIntersectionMat", [ IsMatrix, IsMatrix ] ); +DeclareOperation( "SumIntersectionMat", [ IsMatrixOrMatrixObj, IsMatrixOrMatrixObj ] ); @@ -1349,7 +1349,7 @@ DeclareOperation( "SumIntersectionMat", [ IsMatrix, IsMatrix ] ); ## ## <#/GAPDoc> ## -DeclareOperation( "TriangulizedMat", [ IsMatrix ] ); +DeclareOperation( "TriangulizedMat", [ IsMatrixOrMatrixObj ] ); DeclareSynonym( "RREF", TriangulizedMat); ############################################################################# @@ -1380,7 +1380,7 @@ DeclareSynonym( "RREF", TriangulizedMat); ## ## <#/GAPDoc> ## -DeclareOperation( "TriangulizeMat", [ IsMatrix and IsMutable ] ); +DeclareOperation( "TriangulizeMat", [ IsMatrixOrMatrixObj and IsMutable ] ); ############################################################################# @@ -1574,7 +1574,7 @@ DeclareGlobalFunction( "BlownUpVector" ); ## ## <#/GAPDoc> ## -DeclareOperation( "DiagonalizeMat", [IsRing,IsMatrix and IsMutable] ); +DeclareOperation( "DiagonalizeMat", [IsRing, IsMatrixOrMatrixObj and IsMutable] ); ############################################################################# @@ -2199,7 +2199,7 @@ DeclareSynonymAttr( "TraceMat", TraceMatrix ); ## ## <#/GAPDoc> ## -DeclareAttribute( "JordanDecomposition", IsMatrix ); +DeclareAttribute( "JordanDecomposition", IsMatrixOrMatrixObj ); ############################################################################# @@ -2382,7 +2382,7 @@ DeclareOperation( "CharacteristicPolynomial", ## DeclareOperation("CharacteristicPolynomialMatrixNC", #IsField is not yet known - [IsRing,IsOrdinaryMatrix,IsPosInt]); + [IsRing,IsMatrixOrMatrixObj,IsPosInt]); ############################################################################# @@ -2400,7 +2400,7 @@ DeclareOperation("CharacteristicPolynomialMatrixNC", ## DeclareOperation("MinimalPolynomialMatrixNC", #IsField is not yet known - [IsRing,IsOrdinaryMatrix,IsPosInt]); + [IsRing,IsMatrixOrMatrixObj,IsPosInt]); ############################################################################# ## diff --git a/lib/matrix.gi b/lib/matrix.gi index 569d65c5b9..11b16fb563 100644 --- a/lib/matrix.gi +++ b/lib/matrix.gi @@ -805,7 +805,7 @@ InstallMethod( CharacteristicPolynomial, "spinning over field", fi; return false; end, - [ IsField, IsField, IsOrdinaryMatrix, IsPosInt ], + [ IsField, IsField, IsMatrixOrMatrixObj, IsPosInt ], function( F, E, mat, inum ) local B; @@ -824,7 +824,7 @@ InstallMethod( CharacteristicPolynomial, "spinning over field", InstallMethod( CharacteristicPolynomialMatrixNC, "spinning over field", IsElmsCollsX, - [ IsField, IsOrdinaryMatrix, IsPosInt ], + [ IsField, IsMatrixOrMatrixObj, IsPosInt ], Matrix_CharacteristicPolynomialSameField); InstallOtherMethod( CharacteristicPolynomial, @@ -868,7 +868,7 @@ InstallOtherMethod( CharacteristicPolynomialMatrixNC, InstallMethod( MinimalPolynomial, "spinning over field", IsElmsCollsX, - [ IsField, IsOrdinaryMatrix, IsPosInt ], + [ IsField, IsMatrixOrMatrixObj, IsPosInt ], function( F, mat,inum ) local fld, B; @@ -905,7 +905,7 @@ end); InstallMethod( MinimalPolynomialMatrixNC, "spinning over field", IsElmsCollsX, - [ IsField, IsOrdinaryMatrix, IsPosInt ], + [ IsField, IsMatrixOrMatrixObj, IsPosInt ], Matrix_MinimalPolynomialSameField); InstallOtherMethod( MinimalPolynomial, @@ -1597,7 +1597,7 @@ end); ## InstallMethod( DeterminantMatDestructive, "fraction-free method", - [ IsOrdinaryMatrix and IsMutable], + [ IsMatrixOrMatrixObj and IsMutable], function ( mat ) local det, sgn, row, zero, m, i, j, k, mult, row2, piv; @@ -1668,7 +1668,7 @@ end); ## through here also. ## InstallMethod( DeterminantMatDestructive,"non fraction free", - [ IsOrdinaryMatrix and IsFFECollColl and IsMutable], + [ IsMatrixOrMatrixObj and IsFFECollColl and IsMutable], function( mat ) local m, zero, det, sgn, k, j, row, l, row2, x; @@ -1743,7 +1743,7 @@ InstallMethod( DeterminantMat, end ); InstallMethod( DeterminantMatDestructive,"nonprime residue rings", - [ IsOrdinaryMatrix and + [ IsMatrixOrMatrixObj and CategoryCollections(CategoryCollections(IsZmodnZObjNonprime)) and IsMutable], DeterminantMatDivFree); @@ -1779,7 +1779,7 @@ InstallMethod( DeterminantMatDestructive,"nonprime residue rings", ## InstallMethod( DeterminantMatDivFree, "Division-free method", - [ IsMatrix ], + [ IsMatrixOrMatrixObj ], function ( M ) local u,v,w,i, ## indices a,b,c,x,y, ## temp indices @@ -2335,7 +2335,7 @@ end ); ## InstallMethod( NullspaceMat, "generic method for ordinary matrices", - [ IsOrdinaryMatrix ], + [ IsMatrixOrMatrixObj ], mat -> SemiEchelonMatTransformation(mat).relations ); InstallOtherMethod(NullspaceMat,"matrix objects",[IsMatrixObj], @@ -2356,7 +2356,7 @@ end); InstallMethod( NullspaceMatDestructive, "generic method for ordinary matrices", - [ IsOrdinaryMatrix and IsMutable], + [ IsMatrixOrMatrixObj and IsMutable], mat -> SemiEchelonMatTransformationDestructive(mat).relations ); InstallOtherMethod( TriangulizedNullspaceMat, @@ -2381,7 +2381,7 @@ end ); InstallMethod( TriangulizedNullspaceMatNT, "generic method", - [ IsOrdinaryMatrix ], + [ IsMatrixOrMatrixObj ], function( mat ) local nullspace, n, empty, i, k, row, zero, one;# @@ -2425,7 +2425,7 @@ InstallMethod( TriangulizedNullspaceMatNT, end ); #InstallMethod(TriangulizedNullspaceMat,"generic method", -# [IsOrdinaryMatrix], +# [IsMatrixOrMatrixObj], # function ( mat ) # # triangulize the transposed of the matrix # return TriangulizedNullspaceMatNT( @@ -2433,7 +2433,7 @@ end ); #end ); #InstallMethod(TriangulizedNullspaceMatDestructive,"generic method", -# [IsOrdinaryMatrix], +# [IsMatrixOrMatrixObj], # function ( mat ) # # triangulize the transposed of the matrix # return TriangulizedNullspaceMatNT( @@ -2545,7 +2545,7 @@ InstallOtherMethod( ProjectiveOrder, ## InstallOtherMethod( RankMatDestructive, "generic method for mutable matrices", - [ IsMatrix and IsMutable ], + [ IsMatrixOrMatrixObj and IsMutable ], function( mat ) mat:= SemiEchelonMatDestructive( mat ); if mat <> fail then @@ -2556,7 +2556,7 @@ InstallOtherMethod( RankMatDestructive, InstallOtherMethod( RankMat, "generic method for matrices", - [ IsMatrix ], + [ IsMatrixOrMatrixObj ], mat -> RankMatDestructive( MutableCopyMatrix( mat ) ) ); From 51da696ec766ecdead296b0598e70658c83919eb Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 10 Jun 2026 16:56:55 +0200 Subject: [PATCH 036/114] Further unify messages before break loop (#6434) * Align and clarify break loop instructions further * Adjust blocks to new late error msg * Regenerate tst/testspecial --- doc/ref/debug.xml | 22 ++++++------ doc/ref/language.xml | 4 +-- doc/ref/methsel.xml | 4 +-- doc/ref/mloop.xml | 34 +++++++++---------- doc/ref/types.xml | 2 +- doc/tut/group.xml | 2 +- doc/tut/lists.xml | 2 +- doc/tut/migrat.xml | 4 +-- doc/tut/opers.xml | 2 +- lib/error.g | 2 +- lib/ffe.gd | 4 +-- lib/grpfp.gd | 6 ++-- lib/grpfp.gi | 6 ++-- lib/init.g | 4 +-- lib/integer.gd | 4 +-- lib/integer.gi | 2 +- lib/methsel2.g | 2 +- lib/oper1.g | 4 +-- src/cyclotom.c | 2 +- src/error.c | 6 ++-- src/gaptime.c | 4 +-- src/vec8bit.c | 8 ++--- src/vecgf2.c | 4 +-- .../64bit/low-mem-list-types.g.out | 6 ++-- tst/testspecial/64bit/low-mem-plist-1.g.out | 4 +-- tst/testspecial/64bit/low-mem-plist-2.g.out | 4 +-- tst/testspecial/backtrace.g.out | 34 +++++++++---------- tst/testspecial/backtrace2.g.out | 8 ++--- tst/testspecial/bad-add.g.out | 2 +- tst/testspecial/bad-array-double-1.g.out | 2 +- tst/testspecial/bad-array-int-0.g.out | 2 +- tst/testspecial/bad-array-int-1.g.out | 2 +- tst/testspecial/bad-array-string.g.out | 2 +- tst/testspecial/bad-array-undef-0.g.out | 2 +- tst/testspecial/bad-array-undef-1.g.out | 2 +- tst/testspecial/bad-minus.g.out | 2 +- tst/testspecial/break-loop-loop.g.out | 4 +-- tst/testspecial/broken-test.g.out | 18 +++++----- .../bugfix-2019-09-27-LastPV.g.out | 2 +- tst/testspecial/current-env.g.out | 4 +-- tst/testspecial/debug-var.g.out | 16 ++++----- .../error-in-InputTextString.g.out | 2 +- .../func-and-proc-call-trace.g.out | 32 ++++++++--------- tst/testspecial/last-access.g.out | 4 +-- tst/testspecial/line-continuation.g.out | 8 ++--- tst/testspecial/mem-overflow.g.out | 4 +-- tst/testspecial/method-not-found-where.g.out | 2 +- tst/testspecial/method-not-found.g.out | 2 +- tst/testspecial/print-formatting.g.out | 2 +- tst/testspecial/repl-syntax-err.g.out | 4 +-- tst/testspecial/stack-depth-func.g.out | 8 ++--- tst/testspecial/stack-depth-func2.g.out | 8 ++--- tst/testspecial/stack-depth-rec.g.out | 8 ++--- tst/testspecial/stack-trace-depth.g.out | 4 +-- tst/testspecial/stack-trace-label.g.out | 4 +-- tst/testspecial/syntax-tree-error.g.out | 4 +-- tst/testspecial/top-level-error.g.out | 4 +-- tst/testspecial/up-down-env.g.out | 6 ++-- 58 files changed, 178 insertions(+), 178 deletions(-) diff --git a/doc/ref/debug.xml b/doc/ref/debug.xml index 92f55cff95..5f5b77f9d7 100644 --- a/doc/ref/debug.xml +++ b/doc/ref/debug.xml @@ -43,7 +43,7 @@ gap> IsNormal(2,2); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `IsNormal' on 2 arguments called from read-eval loop at *stdin*:1 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> ]]>

@@ -923,8 +923,8 @@ Stack trace: [2] dive( depth - 1 ); @ *stdin*:1 ... at *stdin*:4 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; gap> dive(11000); Error, recursion depth trap (5000) @@ -934,8 +934,8 @@ Stack trace: [2] dive( depth - 1 ); @ *stdin*:1 ... at *stdin*:5 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; Error, recursion depth trap (10000) Stack trace: @@ -944,8 +944,8 @@ Stack trace: [2] dive( depth - 1 ); @ *stdin*:1 ... at *stdin*:5 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; gap> ]]> @@ -988,8 +988,8 @@ Stack trace: [2] dive( depth - 1 ); @ *stdin*:4 ... at *stdin*:12 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; Error, recursion depth trap (2000) Stack trace: @@ -998,8 +998,8 @@ Stack trace: [2] dive( depth - 1 ); @ *stdin*:4 ... at *stdin*:12 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> GetRecursionDepth(); 0 brk> return; diff --git a/doc/ref/language.xml b/doc/ref/language.xml index b4fbfefcaa..b0e03199ff 100644 --- a/doc/ref/language.xml +++ b/doc/ref/language.xml @@ -717,7 +717,7 @@ gap> MakeReadOnlyGlobal("xx"); gap> xx := 16; Error, Variable: 'xx' is read only not in any function at *stdin*:3 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> IsReadOnlyGlobal("xx"); true @@ -1566,7 +1566,7 @@ Stack trace: @ *stdin*:2 ( ) called from read-eval loop at *stdin*:3 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> ]]>

diff --git a/doc/ref/methsel.xml b/doc/ref/methsel.xml index 1ce2674710..5e88dabef2 100644 --- a/doc/ref/methsel.xml +++ b/doc/ref/methsel.xml @@ -127,13 +127,13 @@ gap> XCons(IsFullTransformationMonoid,4); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `XCons' on 2 arguments called from read-eval loop at *stdin*:8 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> XCons(IsNilpotentGroup,4); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `XCons' on 2 arguments called from read-eval loop at *stdin*:8 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> ]]> diff --git a/doc/ref/mloop.xml b/doc/ref/mloop.xml index a13c30e6c8..8b9aef83fa 100644 --- a/doc/ref/mloop.xml +++ b/doc/ref/mloop.xml @@ -478,7 +478,7 @@ indicate that you are in a break loop. gap> 1/0; Error, Rational operations: must not be zero not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop ]]>

If errors occur within a break loop &GAP; enters another break loop at a @@ -488,7 +488,7 @@ If errors occur within a break loop &GAP; enters another break loop at a brk> 1/0; Error, Rational operations: must not be zero not in any function at *errin*:1 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk_2> ]]>

@@ -567,8 +567,8 @@ function( ) ... end gap> Error("!\n"); Error, ! Hello -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; ]]>

@@ -634,8 +634,8 @@ Here is a somewhat trivial demonstration of the use of gap> ErrorNoTraceBack("Gidday!", " How's", " it", " going?\n"); Error, Gidday! How's it going? -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; ]]>

@@ -645,8 +645,8 @@ Now we call with the same arguments to show the difference. gap> Error("Gidday!", " How's", " it", " going?\n"); Error, Gidday! How's it going? Hello -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; ]]>

@@ -668,7 +668,7 @@ gap> OnBreak := Where;; Break loop message When a break loop is entered by a call to -the message at the end starting with you can 'quit;' to ... +the message at the end starting with you can enter 'quit;' to ... is produced by the function OnBreakMessage, which just like is a user-configurable global variable @@ -676,8 +676,8 @@ that is a function with no arguments.

OnBreakMessage(); # By default, OnBreakMessage prints the following -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue ]]>

Perhaps you are familiar with what's possible in a break loop, and so @@ -751,8 +751,8 @@ Error, user interrupt @ GAPROOT/lib/stbc.gi:18 ( ) called from read-eval loop at *stdin*:2 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> Where(2); *[1] genlabels := Filtered( genlabels, function ( x ) return pnt ^ sgs[x] = pnt; @@ -825,8 +825,8 @@ gap> test:= function( n ) > if n > 3 then Error( "!\n" ); fi; test( n+1 ); end;; gap> test( 1 ); Error, ! -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> Where(); Stack trace: *[1] Error( "!\n" ); @@ -908,8 +908,8 @@ Stack trace: @ *stdin*:7 ( ) called from read-eval loop at *stdin*:8 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> x; 1 brk> DownEnv(1); diff --git a/doc/ref/types.xml b/doc/ref/types.xml index cc80d788a6..b49fe1ad2f 100644 --- a/doc/ref/types.xml +++ b/doc/ref/types.xml @@ -603,7 +603,7 @@ for an object. gap> Setter( prop )( Rationals, false ); Error, You cannot set an "and-filter" except to true not in any function at *stdin*:8 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> ]]> diff --git a/doc/tut/group.xml b/doc/tut/group.xml index f8b1020368..a47c55dec9 100644 --- a/doc/tut/group.xml +++ b/doc/tut/group.xml @@ -933,7 +933,7 @@ Stack trace: @ GAPROOT/lib/mapping.gi:262 ( ) called from read-eval loop at *stdin*:7 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; ]]>

diff --git a/doc/tut/lists.xml b/doc/tut/lists.xml index 0361f480bb..e2f8393cc6 100644 --- a/doc/tut/lists.xml +++ b/doc/tut/lists.xml @@ -343,7 +343,7 @@ gap> list[3][5] := 'w';; list; copy; gap> copy[3][5] := 'w'; Error, List Assignment: must be a mutable list not in any function at *stdin*:3 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; ]]>

diff --git a/doc/tut/migrat.xml b/doc/tut/migrat.xml index 13cdad7898..cf182c4fc2 100644 --- a/doc/tut/migrat.xml +++ b/doc/tut/migrat.xml @@ -856,8 +856,8 @@ gap> test:= function( n ) > if n > 3 then Error( "!\n" ); fi; test( n+1 ); end;; gap> test( 1 ); Error, ! -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> Where(); Stack trace: *[1] Error( "!\n" ); diff --git a/doc/tut/opers.xml b/doc/tut/opers.xml index 6413348e73..313bdc7faf 100644 --- a/doc/tut/opers.xml +++ b/doc/tut/opers.xml @@ -218,7 +218,7 @@ stops with an error message of the form Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `Size' on 1 arguments called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop ]]>

You would get an error message as above if you asked for Size( 1 ). diff --git a/lib/error.g b/lib/error.g index 0daa77277a..3a81bebffd 100644 --- a/lib/error.g +++ b/lib/error.g @@ -449,7 +449,7 @@ BIND_GLOBAL("ErrorNoReturn", function(arg) rec( context := ParentLVars(GetCurrentLVars()), mayReturnVoid := false, - lateMessage := "type 'quit;' to quit to outer loop", + lateMessage := "you can enter 'quit;' to quit to outer loop", ), arg); end); diff --git a/lib/ffe.gd b/lib/ffe.gd index 1bd089717a..aa93c7a24f 100644 --- a/lib/ffe.gd +++ b/lib/ffe.gd @@ -128,8 +128,8 @@ ## @ GAPROOT/lib/ffeconway.gi:167 ## ( ) ## called from read-eval loop at *stdin*:2 -## you can 'quit;' to quit to outer loop, or -## you can 'return;' to continue +## you can enter 'quit;' to quit to outer loop, or +## you can enter 'return;' to continue ## brk> ## ]]> ## diff --git a/lib/grpfp.gd b/lib/grpfp.gd index eaa41d6421..8e373a6ec3 100644 --- a/lib/grpfp.gd +++ b/lib/grpfp.gd @@ -90,9 +90,9 @@ fi; ## [5] CosetTableInWholeGroup( H ) ## @ GAPROOT/lib/grpfp.gi:1733 ## ... at *stdin*:3 -## type 'return;' if you want to continue with a new limit of 8192000 cosets, -## type 'quit;' if you want to quit the coset enumeration, -## type 'maxlimit := 0; return;' in order to continue without a limit +## you can enter 'return;' to continue with a new limit of 8192000 cosets, +## you can enter 'quit;' to abort the coset enumeration, +## you can enter 'maxlimit := 0; return;' in order to continue without a limit ## brk> quit; ## ]]> ##

diff --git a/lib/grpfp.gi b/lib/grpfp.gi index 3eaee5e44e..414ee482c8 100644 --- a/lib/grpfp.gi +++ b/lib/grpfp.gi @@ -1113,10 +1113,10 @@ BindGlobal("GTC_CosetTableFromGensAndRels",function(arg) # to give tidy instructions if one enters a break-loop SavedOnBreakMessage := OnBreakMessage; TCEOnBreakMessage := function(n) - Print( "type 'return;' if you want to continue with a new limit of ", + Print( "you can enter 'return;' to continue with a new limit of ", n, " cosets,\n", - "type 'quit;' if you want to quit the coset enumeration,\n", - "type 'maxlimit := 0; return;' in order to continue without a ", + "you can enter 'quit;' to abort the coset enumeration,\n", + "you can enter 'maxlimit := 0; return;' in order to continue without a ", "limit\n" ); OnBreakMessage := SavedOnBreakMessage; end; diff --git a/lib/init.g b/lib/init.g index 82c828d242..f6061f1e58 100644 --- a/lib/init.g +++ b/lib/init.g @@ -34,8 +34,8 @@ OnBreak := function() Print("An error has occurred before the traceback ", ## break loop. ## OnBreakMessage := function() - Print("you can 'quit;' to quit to outer loop, or\n", - "you can 'return;' to continue\n"); + Print("you can enter 'quit;' to quit to outer loop, or\n", + "you can enter 'return;' to continue\n"); end; ############################################################################# diff --git a/lib/integer.gd b/lib/integer.gd index c2ae9c8ac8..29be88cae8 100644 --- a/lib/integer.gd +++ b/lib/integer.gd @@ -254,8 +254,8 @@ DeclareGlobalFunction( "BestQuoInt" ); ## @ GAPROOT/lib/integer.gi:391 ## ( ) ## called from read-eval loop at *stdin*:2 -## you can 'quit;' to quit to outer loop, or -## you can 'return;' to continue +## you can enter 'quit;' to quit to outer loop, or +## you can enter 'return;' to continue ## brk> ## ]]> ## diff --git a/lib/integer.gi b/lib/integer.gi index b5da9421d7..9928ff6cb3 100644 --- a/lib/integer.gi +++ b/lib/integer.gi @@ -727,7 +727,7 @@ InstallGlobalFunction(FactorsInt,function ( n ) return Factors(n_orig); else Error( "sorry, cannot factor ", tmp[2], - "\ntype 'return;' to try again with a larger number of trials in\n", + "\nyou can enter 'return;' to try again with a larger number of trials in\n", "FactorsRho (or use option 'RhoTrials')\n"); if ValueOption("RhoTrials") <> fail then rt := 5 * ValueOption("RhoTrials"); diff --git a/lib/methsel2.g b/lib/methsel2.g index 45a5f471b0..a56b928f5a 100644 --- a/lib/methsel2.g +++ b/lib/methsel2.g @@ -252,7 +252,7 @@ end; context := GetCurrentLVars(), tracebackContext := ParentLVars(GetCurrentLVars()), mayReturnVoid := false, - lateMessage := "type 'quit;' to quit to outer loop" + lateMessage := "you can enter 'quit;' to quit to outer loop" ), [ no_method_found ]); end; diff --git a/lib/oper1.g b/lib/oper1.g index 1abc10d131..23550e1d7c 100644 --- a/lib/oper1.g +++ b/lib/oper1.g @@ -936,8 +936,8 @@ end); ## @ GAPROOT/lib/oper1.g:1007 ## ( ) ## called from read-eval loop at *stdin*:3 -## you can 'quit;' to quit to outer loop, or -## you can 'return;' to continue +## you can enter 'quit;' to quit to outer loop, or +## you can enter 'return;' to continue ## brk> quit; ## ]]> ##

diff --git a/src/cyclotom.c b/src/cyclotom.c index 9c56dde8e3..17b61a3c03 100644 --- a/src/cyclotom.c +++ b/src/cyclotom.c @@ -836,7 +836,7 @@ static UInt FindCommonField(UInt nl, UInt nr, UInt *ml, UInt *mr) "This computation requires a cyclotomic field of degree %d, larger " "than the current limit of %d", n, (Int)CyclotomicsLimit, - "you can 'return;' after raising the limit with SetCyclotomicsLimit"); + "you can enter 'return;' after raising the limit with SetCyclotomicsLimit"); } // Finish up diff --git a/src/error.c b/src/error.c index b392cd4302..325a661234 100644 --- a/src/error.c +++ b/src/error.c @@ -493,10 +493,10 @@ void ErrorMayQuitNrAtLeastArgs(Int narg, Int actual) void ErrorReturnVoid(const Char * msg, Int arg1, Int arg2, const Char * msg2) { if (msg2 == 0) { - msg2 = "you can 'return;' to continue"; + msg2 = "you can enter 'return;' to continue"; } - Obj lateMsg = MakeString("you can 'quit;' to quit to outer loop, or\n"); + Obj lateMsg = MakeString("you can enter 'quit;' to quit to outer loop, or\n"); AppendString(lateMsg, MakeString(msg2)); CallErrorInner(msg, arg1, arg2, 0, 1, lateMsg); } @@ -507,7 +507,7 @@ void ErrorReturnVoid(const Char * msg, Int arg1, Int arg2, const Char * msg2) */ void ErrorMayQuit(const Char * msg, Int arg1, Int arg2) { - Obj LateMsg = MakeString("type 'quit;' to quit to outer loop"); + Obj LateMsg = MakeString("you can enter 'quit;' to quit to outer loop"); CallErrorInner(msg, arg1, arg2, 0, 0, LateMsg); Panic("ErrorMayQuit must not return"); } diff --git a/src/gaptime.c b/src/gaptime.c index affa0895ac..4bc40fe55f 100644 --- a/src/gaptime.c +++ b/src/gaptime.c @@ -315,7 +315,7 @@ static Obj FuncSleep(Obj self, Obj secs) if (HaveInterrupt()) { ClearError(); // The interrupt may still be pending ErrorReturnVoid("user interrupt in sleep", 0, 0, - "you can 'return;' as if the sleep was finished"); + "you can enter 'return;' as if the sleep was finished"); } return 0; @@ -339,7 +339,7 @@ static Obj FuncMicroSleep(Obj self, Obj msecs) ClearError(); // The interrupt may still be pending ErrorReturnVoid( "user interrupt in microsleep", 0, 0, - "you can 'return;' as if the microsleep was finished"); + "you can enter 'return;' as if the microsleep was finished"); } return 0; diff --git a/src/vec8bit.c b/src/vec8bit.c index 1b583895a8..83f34e0657 100644 --- a/src/vec8bit.c +++ b/src/vec8bit.c @@ -3002,7 +3002,7 @@ void ASS_VEC8BIT(Obj list, Obj pos, Obj elm) ErrorReturnVoid("List assignment would increase length of " "locked compressed vector", 0, 0, - "you can 'return;' to ignore the assignment"); + "you can enter 'return;' to ignore the assignment"); return; } ResizeWordSizedBag(list, SIZE_VEC8BIT(p, elts)); @@ -3094,7 +3094,7 @@ static Obj FuncUNB_VEC8BIT(Obj self, Obj list, Obj pos) if (True == DoFilter(IsLockedRepresentationVector, list)) { ErrorReturnVoid( "Unbind of entry of locked compressed vector is forbidden", 0, 0, - "you can 'return;' to ignore the assignment"); + "you can enter 'return;' to ignore the assignment"); return 0; } @@ -3220,7 +3220,7 @@ static Obj FuncAPPEND_VEC8BIT(Obj self, Obj vecl, Obj vecr) lenr = LEN_VEC8BIT(vecr); if (True == DoFilter(IsLockedRepresentationVector, vecl) && lenr > 0) { ErrorReturnVoid("Append to locked compressed vector is forbidden", 0, - 0, "you can 'return;' to ignore the operation"); + 0, "you can enter 'return;' to ignore the operation"); return 0; } info = GetFieldInfo8Bit(FIELD_VEC8BIT(vecl)); @@ -4369,7 +4369,7 @@ static void ResizeVec8Bit(Obj vec, UInt newlen, UInt knownclean) if (True == DoFilter(IsLockedRepresentationVector, vec)) { ErrorReturnVoid("Resize of locked compressed vector is forbidden", 0, - 0, "you can 'return;' to ignore the operation"); + 0, "you can enter 'return;' to ignore the operation"); return; } diff --git a/src/vecgf2.c b/src/vecgf2.c index c484531c5f..d61c046c3a 100644 --- a/src/vecgf2.c +++ b/src/vecgf2.c @@ -3826,7 +3826,7 @@ FuncREDUCE_COEFFS_GF2VEC(Obj self, Obj vec1, Obj len1, Obj vec2, Obj len2) if (len2a == 0) { ErrorReturnVoid("ReduceCoeffs: second argument must not be zero", 0, - 0, "you can 'return;' to skip the reduction"); + 0, "you can enter 'return;' to skip the reduction"); return 0; } @@ -3872,7 +3872,7 @@ FuncQUOTREM_COEFFS_GF2VEC(Obj self, Obj vec1, Obj len1, Obj vec2, Obj len2) } if (len2a == 0) { ErrorReturnVoid("QuotremCoeffs: second argument must not be zero", 0, - 0, "you can 'return;' to skip the reduction"); + 0, "you can enter 'return;' to skip the reduction"); return 0; } diff --git a/tst/testspecial/64bit/low-mem-list-types.g.out b/tst/testspecial/64bit/low-mem-list-types.g.out index b8c7f74302..87dff93393 100644 --- a/tst/testspecial/64bit/low-mem-list-types.g.out +++ b/tst/testspecial/64bit/low-mem-list-types.g.out @@ -1,16 +1,16 @@ gap> ListWithIdenticalEntries(2^50, 'a'); Error, Cannot allocate 1125899906842633 bytes: cannot extend the workspace any more!! not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> ListWithIdenticalEntries(2^50, true); Error, Cannot allocate 140737488355336 bytes: cannot extend the workspace any more!! not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> ListWithIdenticalEntries(2^50, 2); Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!! not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> quit; diff --git a/tst/testspecial/64bit/low-mem-plist-1.g.out b/tst/testspecial/64bit/low-mem-plist-1.g.out index f3bdaee9b0..921fd7e60e 100644 --- a/tst/testspecial/64bit/low-mem-plist-1.g.out +++ b/tst/testspecial/64bit/low-mem-plist-1.g.out @@ -3,12 +3,12 @@ gap> l := []; gap> l[2^50] := 1; Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!!!! not in any function at *stdin*:3 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> l[2^50] := 2; Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!!!! not in any function at *stdin*:3 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> l[3] := 3; 3 diff --git a/tst/testspecial/64bit/low-mem-plist-2.g.out b/tst/testspecial/64bit/low-mem-plist-2.g.out index 3d430e5bb8..757b353f3d 100644 --- a/tst/testspecial/64bit/low-mem-plist-2.g.out +++ b/tst/testspecial/64bit/low-mem-plist-2.g.out @@ -1,11 +1,11 @@ gap> EmptyPlist(2^50); Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!! not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> EmptyPlist(2^50); Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!! not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> quit; diff --git a/tst/testspecial/backtrace.g.out b/tst/testspecial/backtrace.g.out index c29cadf6fc..053849a831 100644 --- a/tst/testspecial/backtrace.g.out +++ b/tst/testspecial/backtrace.g.out @@ -18,7 +18,7 @@ Stack trace: @ *stdin*:11 ( ) called from read-eval loop at *stdin*:13 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] l[[ 1 .. 3 ]] := 1; @@ -45,7 +45,7 @@ Stack trace: @ *stdin*:15 ( ) called from read-eval loop at *stdin*:16 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] 1 / 0 @@ -73,7 +73,7 @@ fi; @ *stdin*:18 ( ) called from read-eval loop at *stdin*:19 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] if x then @@ -106,7 +106,7 @@ fi; @ *stdin*:21 ( ) called from read-eval loop at *stdin*:22 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] if 1 then @@ -140,7 +140,7 @@ fi; @ *stdin*:24 ( ) called from read-eval loop at *stdin*:25 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] if 1 < 0 then @@ -176,7 +176,7 @@ od; @ *stdin*:27 ( ) called from read-eval loop at *stdin*:28 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] while 1 do @@ -210,8 +210,8 @@ od; @ *stdin*:30 ( ) called from read-eval loop at *stdin*:31 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> Where(); Stack trace: *[1] Error( "You cannot loop over the integer ", n, " did you mean the range [1..", n, "]" ); @@ -252,7 +252,7 @@ od; @ *stdin*:33 ( ) called from read-eval loop at *stdin*:34 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] for i in true do @@ -285,7 +285,7 @@ od; @ *stdin*:35 ( ) called from read-eval loop at *stdin*:36 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] for i in true do @@ -320,7 +320,7 @@ od; @ *stdin*:37 ( ) called from read-eval loop at *stdin*:38 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] for i in true do @@ -355,7 +355,7 @@ od; @ *stdin*:39 ( ) called from read-eval loop at *stdin*:40 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] for i in true do @@ -389,7 +389,7 @@ until 1; @ *stdin*:41 ( ) called from read-eval loop at *stdin*:42 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] repeat @@ -420,7 +420,7 @@ Stack trace: @ *stdin*:44 ( ) called from read-eval loop at *stdin*:45 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] Assert( 0, 1 ); @@ -447,7 +447,7 @@ Stack trace: @ *stdin*:47 ( ) called from read-eval loop at *stdin*:48 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] Assert( 0, 1, "hello" ); @@ -483,7 +483,7 @@ Stack trace: @ *stdin*:55 ( ) called from read-eval loop at *stdin*:56 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); Stack trace: *[1] return m[i][j]; @@ -531,5 +531,5 @@ Stack trace: @ GAPROOT/lib/oper1.g:LINE ( ) called from read-eval loop at *stdin*:61 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/backtrace2.g.out b/tst/testspecial/backtrace2.g.out index 51ade71f0c..2633405b76 100644 --- a/tst/testspecial/backtrace2.g.out +++ b/tst/testspecial/backtrace2.g.out @@ -35,8 +35,8 @@ Stack trace: @ *stdin*:26 ( ) called from read-eval loop at *stdin*:28 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> n; Where(); 3 Stack trace: @@ -137,7 +137,7 @@ Stack trace: @ *stdin*:37 ( ) called from read-eval loop at *stdin*:39 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> n; Where(); 3 Stack trace: @@ -240,7 +240,7 @@ Stack trace: @ *stdin*:49 ( ) called from read-eval loop at *stdin*:51 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> n; Where(); 3 Stack trace: diff --git a/tst/testspecial/bad-add.g.out b/tst/testspecial/bad-add.g.out index 9259da66d3..0dcbbfff42 100644 --- a/tst/testspecial/bad-add.g.out +++ b/tst/testspecial/bad-add.g.out @@ -10,5 +10,5 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-array-double-1.g.out b/tst/testspecial/bad-array-double-1.g.out index a68076d65a..05de996ca7 100644 --- a/tst/testspecial/bad-array-double-1.g.out +++ b/tst/testspecial/bad-array-double-1.g.out @@ -10,5 +10,5 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-array-int-0.g.out b/tst/testspecial/bad-array-int-0.g.out index 17e703a17a..2a307b9437 100644 --- a/tst/testspecial/bad-array-int-0.g.out +++ b/tst/testspecial/bad-array-int-0.g.out @@ -12,5 +12,5 @@ Stack trace: @ *stdin*:5 ( ) called from read-eval loop at *stdin*:7 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-array-int-1.g.out b/tst/testspecial/bad-array-int-1.g.out index cd7a87a095..ae359c3547 100644 --- a/tst/testspecial/bad-array-int-1.g.out +++ b/tst/testspecial/bad-array-int-1.g.out @@ -9,5 +9,5 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-array-string.g.out b/tst/testspecial/bad-array-string.g.out index d0bd81ee20..34dd31bbd0 100644 --- a/tst/testspecial/bad-array-string.g.out +++ b/tst/testspecial/bad-array-string.g.out @@ -10,5 +10,5 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-array-undef-0.g.out b/tst/testspecial/bad-array-undef-0.g.out index 5ea205de9a..8ce908cbd9 100644 --- a/tst/testspecial/bad-array-undef-0.g.out +++ b/tst/testspecial/bad-array-undef-0.g.out @@ -10,5 +10,5 @@ Stack trace: @ *stdin*:4 ( ) called from read-eval loop at *stdin*:6 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-array-undef-1.g.out b/tst/testspecial/bad-array-undef-1.g.out index 7efcc85219..d172c4f20f 100644 --- a/tst/testspecial/bad-array-undef-1.g.out +++ b/tst/testspecial/bad-array-undef-1.g.out @@ -11,5 +11,5 @@ Stack trace: @ *stdin*:5 ( ) called from read-eval loop at *stdin*:7 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-minus.g.out b/tst/testspecial/bad-minus.g.out index ec55c46e87..42a34245bd 100644 --- a/tst/testspecial/bad-minus.g.out +++ b/tst/testspecial/bad-minus.g.out @@ -14,5 +14,5 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/break-loop-loop.g.out b/tst/testspecial/break-loop-loop.g.out index 4da0087abd..c1f24f4ce9 100644 --- a/tst/testspecial/break-loop-loop.g.out +++ b/tst/testspecial/break-loop-loop.g.out @@ -9,8 +9,8 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> x; 1 brk> y; diff --git a/tst/testspecial/broken-test.g.out b/tst/testspecial/broken-test.g.out index bbe429da39..f51326c8ce 100644 --- a/tst/testspecial/broken-test.g.out +++ b/tst/testspecial/broken-test.g.out @@ -9,7 +9,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-3.tst", rec(width := 800)); Error, Invalid test file at broken-test-3.tst:5 @@ -22,7 +22,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-4.tst", rec(width := 800)); Error, Invalid test file: Nested #@if at broken-test-4.tst:2 @@ -35,7 +35,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-5.tst", rec(width := 800)); Error, Invalid test file: two #@else at broken-test-5.tst:7 @@ -48,7 +48,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-6.tst", rec(width := 800)); Error, Invalid test file: Continuation prompt '> ' followed by a tab, expected a regular space at broken-test-6.tst:3 @@ -61,7 +61,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-7.tst", rec(width := 800)); Error, Invalid test file: #@elif after #@else at broken-test-7.tst:7 @@ -74,7 +74,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-8.tst", rec(width := 800)); Error, Invalid test file: #@elif without #@if at broken-test-8.tst:1 @@ -87,7 +87,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-9.tst", rec(width := 800)); Error, Invalid test file: Unterminated #@if at broken-test-9.tst:7 @@ -100,7 +100,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("invalidtestfile.tst", rec(width := 800)); Error, Invalid test file at invalidtestfile.tst:7 @@ -113,7 +113,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("empty.tst", rec(width := 800)); #I Test: File does not contain any tests! diff --git a/tst/testspecial/bugfix-2019-09-27-LastPV.g.out b/tst/testspecial/bugfix-2019-09-27-LastPV.g.out index bfb7f37450..c10ae80f68 100644 --- a/tst/testspecial/bugfix-2019-09-27-LastPV.g.out +++ b/tst/testspecial/bugfix-2019-09-27-LastPV.g.out @@ -7,7 +7,7 @@ gap> old_OnBreak:=OnBreak;; gap> OnBreak:=fail;; # prevent backtrace with line numbers that keep chaning gap> View([[badgroup]]); # <- trigger break loop Error, Rational operations: must not be zero -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; [ [ gap> OnBreak:=old_OnBreak;; diff --git a/tst/testspecial/current-env.g.out b/tst/testspecial/current-env.g.out index e90991e7e2..68ec461013 100644 --- a/tst/testspecial/current-env.g.out +++ b/tst/testspecial/current-env.g.out @@ -16,8 +16,8 @@ od; @ *stdin*:6 ( ) called from read-eval loop at *stdin*:9 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> ContentsLVars(CurrentEnv()); rec( func := function( n ) ... end, names := [ "n" ], values := [ 1 ] ) brk> DownEnv(); ContentsLVars(CurrentEnv()); diff --git a/tst/testspecial/debug-var.g.out b/tst/testspecial/debug-var.g.out index ab72b2459f..bbff49cdd5 100644 --- a/tst/testspecial/debug-var.g.out +++ b/tst/testspecial/debug-var.g.out @@ -19,8 +19,8 @@ Stack trace: @ *stdin*:12 ( ) called from read-eval loop at *stdin*:14 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> brk> x; # access global 1 @@ -61,7 +61,7 @@ Stack trace: @ *stdin*:12 ( ) called from read-eval loop at *errin*:12 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk_2> quit; brk> brk> z; # access local @@ -80,7 +80,7 @@ Stack trace: @ *stdin*:12 ( ) called from read-eval loop at *errin*:17 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk_2> quit; brk> brk> return; @@ -106,8 +106,8 @@ Stack trace: @ *stdin*:12 ( ) called from read-eval loop at *stdin*:23 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> h(2); Error, foobar Stack trace: @@ -119,8 +119,8 @@ Stack trace: @ *stdin*:12 ( ) called from read-eval loop at *errin*:1 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk_2> brk_2> y; # access higher local as debug var 2 diff --git a/tst/testspecial/error-in-InputTextString.g.out b/tst/testspecial/error-in-InputTextString.g.out index 36b19d8b23..f27a402920 100644 --- a/tst/testspecial/error-in-InputTextString.g.out +++ b/tst/testspecial/error-in-InputTextString.g.out @@ -2,6 +2,6 @@ gap> Read(InputTextString("Print(1 + [()]);")); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `+' on 2 arguments called from read-eval loop at stream:1 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> QUIT; diff --git a/tst/testspecial/func-and-proc-call-trace.g.out b/tst/testspecial/func-and-proc-call-trace.g.out index 046b27f874..e58f4ef668 100644 --- a/tst/testspecial/func-and-proc-call-trace.g.out +++ b/tst/testspecial/func-and-proc-call-trace.g.out @@ -10,7 +10,7 @@ Stack trace: @ *stdin*:4 ( ) called from read-eval loop at *stdin*:6 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -27,7 +27,7 @@ Stack trace: @ *stdin*:9 ( ) called from read-eval loop at *stdin*:11 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -44,7 +44,7 @@ Stack trace: @ *stdin*:14 ( ) called from read-eval loop at *stdin*:16 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -61,7 +61,7 @@ Stack trace: @ *stdin*:19 ( ) called from read-eval loop at *stdin*:21 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -78,7 +78,7 @@ Stack trace: @ *stdin*:24 ( ) called from read-eval loop at *stdin*:26 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -95,7 +95,7 @@ Stack trace: @ *stdin*:29 ( ) called from read-eval loop at *stdin*:31 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -112,7 +112,7 @@ Stack trace: @ *stdin*:34 ( ) called from read-eval loop at *stdin*:36 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -129,7 +129,7 @@ Stack trace: @ *stdin*:39 ( ) called from read-eval loop at *stdin*:41 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -146,7 +146,7 @@ Stack trace: @ *stdin*:44 ( ) called from read-eval loop at *stdin*:46 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -163,7 +163,7 @@ Stack trace: @ *stdin*:49 ( ) called from read-eval loop at *stdin*:51 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -180,7 +180,7 @@ Stack trace: @ *stdin*:54 ( ) called from read-eval loop at *stdin*:56 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -197,7 +197,7 @@ Stack trace: @ *stdin*:59 ( ) called from read-eval loop at *stdin*:61 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -214,7 +214,7 @@ Stack trace: @ *stdin*:64 ( ) called from read-eval loop at *stdin*:66 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -231,7 +231,7 @@ Stack trace: @ *stdin*:69 ( ) called from read-eval loop at *stdin*:71 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -248,7 +248,7 @@ Stack trace: @ *stdin*:74 ( ) called from read-eval loop at *stdin*:76 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -265,7 +265,7 @@ Stack trace: @ *stdin*:79 ( ) called from read-eval loop at *stdin*:81 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); diff --git a/tst/testspecial/last-access.g.out b/tst/testspecial/last-access.g.out index 78d756615f..2bc0c8131e 100644 --- a/tst/testspecial/last-access.g.out +++ b/tst/testspecial/last-access.g.out @@ -6,8 +6,8 @@ gap> 1;2;3;[last,last2,last3]; gap> Error("err"); Error, err not in any function at *stdin*:3 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> 1;2;3;[last,last2,last3]; 1 2 diff --git a/tst/testspecial/line-continuation.g.out b/tst/testspecial/line-continuation.g.out index 2f06f33fdc..a6ed2a8a24 100644 --- a/tst/testspecial/line-continuation.g.out +++ b/tst/testspecial/line-continuation.g.out @@ -11,8 +11,8 @@ Stack trace: @ GAPROOT/lib/string.gi:LINE ( ) called from read-eval loop at *stdin*:6 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; gap> EvalString("123\\\r\n45x;"); Error, Variable: '12345x' must have a value @@ -23,7 +23,7 @@ Stack trace: @ GAPROOT/lib/string.gi:LINE ( ) called from read-eval loop at *stdin*:6 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; gap> QUIT; diff --git a/tst/testspecial/mem-overflow.g.out b/tst/testspecial/mem-overflow.g.out index 1f9147a44c..9de037b50f 100644 --- a/tst/testspecial/mem-overflow.g.out +++ b/tst/testspecial/mem-overflow.g.out @@ -7,8 +7,8 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:3 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> # ... then we should be in a break loop. Exit that, perform some other computations. brk> quit; gap> Factorial(42); diff --git a/tst/testspecial/method-not-found-where.g.out b/tst/testspecial/method-not-found-where.g.out index eaaeaee161..5f80b728c7 100644 --- a/tst/testspecial/method-not-found-where.g.out +++ b/tst/testspecial/method-not-found-where.g.out @@ -8,7 +8,7 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:4 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> ShowMethods(1); #I Searching Method for IsDiagonalMatrix with 1 argument: #I Total: 3 entries diff --git a/tst/testspecial/method-not-found.g.out b/tst/testspecial/method-not-found.g.out index fa8a04ad87..2001ae951b 100644 --- a/tst/testspecial/method-not-found.g.out +++ b/tst/testspecial/method-not-found.g.out @@ -7,7 +7,7 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:3 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> return; 'return' cannot be used in this read-eval-print loop brk> QUIT; diff --git a/tst/testspecial/print-formatting.g.out b/tst/testspecial/print-formatting.g.out index 91e7af8741..11a0eb6932 100644 --- a/tst/testspecial/print-formatting.g.out +++ b/tst/testspecial/print-formatting.g.out @@ -23,7 +23,7 @@ gap> # test formatting status for errout gap> 1/0; # trigger a break loop Error, Rational operations: must not be zero not in any function at *stdin*:14 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> old := PrintFormattingStatus("*errout*"); true brk> SetPrintFormattingStatus("*errout*", false); diff --git a/tst/testspecial/repl-syntax-err.g.out b/tst/testspecial/repl-syntax-err.g.out index 7f31dd0233..783de07a05 100644 --- a/tst/testspecial/repl-syntax-err.g.out +++ b/tst/testspecial/repl-syntax-err.g.out @@ -8,8 +8,8 @@ gap> # fixed. gap> Error(""): Error, not in any function at *stdin*:9 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; Syntax error: ; expected Error(""): diff --git a/tst/testspecial/stack-depth-func.g.out b/tst/testspecial/stack-depth-func.g.out index 37a8116566..26446d3435 100644 --- a/tst/testspecial/stack-depth-func.g.out +++ b/tst/testspecial/stack-depth-func.g.out @@ -14,8 +14,8 @@ Stack trace: [5] f( ); @ *stdin*:2 ... at *stdin*:3 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; # try once more Error, recursion depth trap (10000) Stack trace: @@ -30,6 +30,6 @@ Stack trace: [5] f( ); @ *stdin*:2 ... at *stdin*:3 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> QUIT; diff --git a/tst/testspecial/stack-depth-func2.g.out b/tst/testspecial/stack-depth-func2.g.out index d41cac1c18..f82d7ece2f 100644 --- a/tst/testspecial/stack-depth-func2.g.out +++ b/tst/testspecial/stack-depth-func2.g.out @@ -14,8 +14,8 @@ Stack trace: [5] f( ) @ *stdin*:2 ... at *stdin*:3 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; # try once more Error, recursion depth trap (10000) Stack trace: @@ -30,6 +30,6 @@ Stack trace: [5] f( ) @ *stdin*:2 ... at *stdin*:3 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> QUIT; diff --git a/tst/testspecial/stack-depth-rec.g.out b/tst/testspecial/stack-depth-rec.g.out index 3a2f0bcb5a..88d55ca50e 100644 --- a/tst/testspecial/stack-depth-rec.g.out +++ b/tst/testspecial/stack-depth-rec.g.out @@ -82,8 +82,8 @@ Stack trace: [5] String( record.(nam) ) @ GAPROOT/lib/record.gi:LINE ... at *stdin*:4 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; # try once more Error, recursion depth trap (5000) Stack trace: @@ -98,6 +98,6 @@ Stack trace: [5] String( record.(nam) ) @ GAPROOT/lib/record.gi:LINE ... at *stdin*:4 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> QUIT; diff --git a/tst/testspecial/stack-trace-depth.g.out b/tst/testspecial/stack-trace-depth.g.out index 9c12a52a9a..bb06fe9547 100644 --- a/tst/testspecial/stack-trace-depth.g.out +++ b/tst/testspecial/stack-trace-depth.g.out @@ -45,8 +45,8 @@ Stack trace: [5] f8( ) @ *stdin*:15 ... at *stdin*:35 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> SetUserPreference("WhereDepth", 12); brk> Where(); Stack trace: diff --git a/tst/testspecial/stack-trace-label.g.out b/tst/testspecial/stack-trace-label.g.out index a7a71b90c8..2397215b7c 100644 --- a/tst/testspecial/stack-trace-label.g.out +++ b/tst/testspecial/stack-trace-label.g.out @@ -8,7 +8,7 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; gap> QUIT; diff --git a/tst/testspecial/syntax-tree-error.g.out b/tst/testspecial/syntax-tree-error.g.out index 96794103f1..bff4a4d368 100644 --- a/tst/testspecial/syntax-tree-error.g.out +++ b/tst/testspecial/syntax-tree-error.g.out @@ -12,6 +12,6 @@ Stack trace: *[1] ( ) called from read-eval loop at *stdin*:8 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> QUIT; diff --git a/tst/testspecial/top-level-error.g.out b/tst/testspecial/top-level-error.g.out index f27f9df6d9..b4a6915bca 100644 --- a/tst/testspecial/top-level-error.g.out +++ b/tst/testspecial/top-level-error.g.out @@ -1,6 +1,6 @@ gap> Error("foo"); Error, foo not in any function at *stdin*:2 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> QUIT; diff --git a/tst/testspecial/up-down-env.g.out b/tst/testspecial/up-down-env.g.out index 93062e655b..a3c9ea82b0 100644 --- a/tst/testspecial/up-down-env.g.out +++ b/tst/testspecial/up-down-env.g.out @@ -19,7 +19,7 @@ Stack trace: [5] f( lvl - 1 ) @ *stdin*:7 ... at *stdin*:8 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> UpEnv(1); lvl; 0 brk> DownEnv(1); lvl; @@ -56,8 +56,8 @@ brk> ## brk> Read("top-level-error.g"); Error, foo not in any function at top-level-error.g:1 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk_2> Where(20); not in any function at *errin*:1 brk_2> lvl; # since `Read` started a fresh execution context, we can't access lvl here From 0ad351b446f620bfd50180b67550be63a532de69 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 10 Jun 2026 23:11:13 +0200 Subject: [PATCH 037/114] Remove dev/migratedoc.tex and doc/tut/migrat.xml (#6431) They are not referenced anywhere and nowadays at most of historical interest. --- dev/migratedoc.tex | 1141 ---------------------------------------- doc/tut/migrat.xml | 1227 -------------------------------------------- 2 files changed, 2368 deletions(-) delete mode 100644 dev/migratedoc.tex delete mode 100644 doc/tut/migrat.xml diff --git a/dev/migratedoc.tex b/dev/migratedoc.tex deleted file mode 100644 index 8e3f02270e..0000000000 --- a/dev/migratedoc.tex +++ /dev/null @@ -1,1141 +0,0 @@ -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%W migratedoc.tex GAP documentation Thomas Breuer -%W & Frank Celler -%W & Martin Schoenert -%W & Heiko Theissen -%% -%% -%Y Copyright 1997, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany -%% -%% self-contained document with the former chapter -%% ``Migrating to GAP 4'' of the GAP Tutorial -%% -\input gapmacro -\BeginningOfBook{mig} -\TitlePage{ - \centerline{\titlefont GAP}\bigskip - \centerline{\secfont Release 4.5}\medskip - \centerline{\secfont May 2012}\bigskip\bigskip - \centerline{\titlefont Migrating to GAP 4}\vfill - \centerline{\secfont The GAP Group}\bigskip - \centerline{\secfont https://www.gap-system.org} -} -\TableOfContents -\FrontMatter -Copyright {\copyright} (1987-2012) for the core -part of the {\GAP} system by the {\GAP} Group. - -Most parts of the {\GAP} distribution, including -the core part of the {\GAP} system, are distributed -under the terms of the GNU General Public License -(see {\tt{https://www.gnu.org/licenses/gpl.html}} -or the file {\tt GPL} in the {\tt etc} directory -of the {\GAP} installation). - -More detailed information about copyright and -licenses of parts of this distribution can be -found in the {\GAP}~4 Reference manual -(see {\bf Reference: Copyright and License}). - -{\GAP} is developed over a long time and has -many authors and contributors. More detailed -information can be found in the {\GAP}~4 -Reference manual (see {\bf Reference: Authors and Maintainers}). - -\Chapters - -\Chapter{Migrating to GAP 4} - -This chapter is intended to give users who have experience with {\GAP}~3 -some information about what has changed in {\GAP}~4. -In particular, it informs about changed command line options -(see~"Changed Command Line Options"), -the new global variable `fail' (see~"Fail"), -some functions that have changed their behaviour -(see~"Changed Functionality") or their names -(see~"Changed Variable Names"), -and some conventions used for variable names (see~"Naming Conventions"). - -Then the new concepts of {\GAP}~4 are sketched, -first that of mutability or immutability (see~"Immutable Objects"), -with the explanation of related changes in functions that copy objects -(see~"Copy"), -then the concepts of operations and method selection, which are compared -with the use of operations records in {\GAP}~3 -(see~"Attributes vs. Record Components", "Operations Records", -and~"Operations vs. Dispatcher Functions"). - -More local changes affect the concepts of notions of generation -(see~"Different Notions of Generation"), -of parents (see~"Parents and Subgroups"), -of homomorphisms (see~"Homomorphisms vs. General Mappings", -"Homomorphisms vs. Factor Structures", -and~"Isomorphisms vs. Isomorphic Structures"), -how elements in finitely presented groups are treated -(see~"Elements of Finitely Presented Groups"), -how information about progress of computations can be obtained -(see~"The Info Mechanism"), -and how one gets information in a `break' loop -(see~"Debugging"). - -%Commented out: no longer provided with GAP 4.5 -%While a ``{\GAP}~3 compatibility mode'' is provided -%(see "Compatibility Mode"), -%its use will disable some of the new features of {\GAP}~4. -%Also it certainly can only try to provide partial compatibility. - -%For a detailed explanation of the new features and concepts of {\GAP}~4, -%see the manual ``Programming in GAP''. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Changed Command Line Options} - -In {\GAP}~4, the `-l' option is used to specify the *root directory* -(see ``GAP Root Directory'' in the {\GAP}~4 Reference Manual) -of the {\GAP} distribution, -which is the directory containing the `lib' and `doc' subdirectories. -Note that in {\GAP}~3 this option was used to specify the path to the -`lib' directory. - -The `-h' option of {\GAP}~3 has been removed, -the path(s) for the documentation are deduced automatically in {\GAP}~4. - -The option `-g' is now used to print information only about full garbage -collections. -The new option `-g -g' generates information about partial -garbage collections too. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Fail} - -There is a new global variable - -\>`fail'{fail instead of false} - -in {\GAP}~4. -It is intended as a return value of a function for the case that it -could not perform its task. -For example, `Inverse' returns `fail' if it is called with a singular -matrix, and `Position' returns `fail' if the second argument is not -contained in the list given as first argument. - -{\GAP}~3 handled such situations by either signalling an error, -for example if it was asked for the inverse of a singular matrix, -or by (mis)using `false' as return value, as in the example `Position'. -Note that in the first example, in {\GAP}~3 it was necessary to check -the invertibility of a matrix before one could safely ask for its -inverse, which meant that roughly the same work was done twice. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Changed Functionality} - -Some functions that were already available in {\GAP}~3 behave -differently in {\GAP}~4. This section lists them. - -\>Orbit( ,) - -The {\GAP}~3 manual promised that would be the first entry of the -resulting orbit. This was wrong already there in a few cases, therefore -{\GAP}~4 does not promise anything about the ordering of points in an orbit. - -\>Order( ) - -only takes the element and computes its multiplicative order. -%Calling `Order' with two arguments is permitted only in the -%{\GAP}~3 compatibility mode, see~"Compatibility Mode". -(Note that it does not make sense anymore to specify a group as -first argument w.r.t. which the order of the second argument shall -be computed, see~"Elements of Finitely Presented Groups".) - -\>Position( , ) - -If is not contained in the list then `fail' is returned -in {\GAP}~4 (see~"Fail"), whereas `false' was returned in {\GAP}~3. - - -\>PermGroupOps.ElementProperty( , [, ] ) - -In {\GAP}~3, this function took either two or three arguments, -the optional argument being a subgroup of that stabilizes -in the sense that for any element in , -either all elements or no element in the coset ` \* ' have the -property . - -The {\GAP}~4 function `ElementProperty', however, -takes between two and four arguments, -and the subgroup known from {\GAP}~3 has to be entered as the *fourth* -argument *not* the third. -(The third argument in the {\GAP}~4 function denotes a subgroup -stabilizing in the sense that either all elements or no element -in right cosets ` \* ' have the property .) - -(This discrepancy was discovered only in March~2002, -short before the release of {\GAP}~4.3.) - - -\>Print( , ... ) - -Objects may appear on the screen in a different way, -depending on whether they are printed by the read eval print loop -or by an explicit call of `Print'. -The reason is that the read eval print loop calls the operation `ViewObj' -and not `PrintObj', whereas `Print' calls `PrintObj' for each of its -arguments. -This permits the installation of methods for printing objects in a short form -in the read eval print loop while retaining `Print' to display -the object completely. -See also Section ``View and Print'' in the {\GAP}~4 Reference Manual. - -(`PrintObj' is installed as standard method `ViewObj', so it is -not really necessary to have a `ViewObj' method for an object.) - -\>PrintTo( , , ... ) - -In {\GAP}~3, `PrintTo' could be (mis)used to ``redirect'' the text -*printed* by a function (that is, *not* only the output of a function) -to a file by entering the function call as second argument. -This was used mainly in order to avoid many calls of `AppendTo'. -In {\GAP}~4, this feature has disappeared. -One can use streams (see Chapter ``Streams'' in the {\GAP}~4 Reference Manual) -instead in order to write files efficiently. - -\break - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Changed Variable Names} - -\indextt{AgGroup} -\indextt{ApplyFunc} -\indextt{Backtrace} -\indextt{CharTable} -\indextt{Denominator} -\indextt{DepthVector} -\indextt{Elements} -\indextt{IsBijection} -\indextt{IsFunc} -\indextt{IsMat} -\indextt{IsRec} -\indextt{IsSet} -\indextt{LengthWord} -\indextt{NOfCyc} -\indextt{Numerator} -\indextt{RandomInvertableMat} -\indextt{RecFields} -\indextt{X} - -Some functions have changed their name without changing the -functionality. -A -- probably incomplete -- list follows -\begintt - GAP 3 GAP 4 - - AgGroup PcGroup # (also composita) - ApplyFunc CallFuncList - Backtrace Where - CharTable CharacterTable # (also composita) - Denominator DenominatorRat - DepthVector PositionNonZero - Elements AsSSortedList - IsBijection IsBijective - IsFunc IsFunction - IsMat IsMatrix - IsRec IsRecord - IsSet IsSSortedList - LengthWord Length - NOfCyc Conductor - Numerator NumeratorRat - NormedVector NormedRowVector - Operation Action # (also composita) - Order(G,g) Order(g) - OrderMat Order - OrderPerm Order - RandomInvertableMat RandomInvertibleMat - RecFields RecNames - X Indeterminate -\endtt - -%See Section~"Compatibility Mode" for a way to make the old names -%available again. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Naming Conventions} - -The way functions are named has been unified in {\GAP}~4. -This might help to memorize or even guess names of library functions. - -If a variable name consists of several words then the first -letter of each word is capitalized. - -If the first part of the name of a function is a verb then the function -may modify its argument(s) but does not return anything, -for example `Append' appends the list given as second argument to the -list given as first argument. -Otherwise the function returns an object without changing the arguments, -for example `Concatenation' returns the concatenation of the lists -given as arguments. - -If the name of a function contains the word `By' then the return value is -thought of as built in a certain way from the parts given as arguments. -For example, `GroupByGenerators' returns a group built from its group -generators, and creating a group as a factor group of a given group -by a normal subgroup can be done by taking the image of -`NaturalHomomorphismByNormalSubgroup' -(see also~"Homomorphisms vs. Factor Structures"). -Other examples of ```By''' functions are `GroupHomomorphismByImages' and -`UnivariateLaurentPolynomialByCoefficients'. - -If the name of a function contains the word `Of' then the return value is -thought of as information deduced from the arguments. -Usually such functions are attributes -(see ``Attributes'' in the {\GAP}~4 Reference Manual). -Examples are `GeneratorsOfGroup', which returns a list of generators for -the group entered as argument, or `DiagonalOfMat'. - -For the setter and tester functions of an attribute -(see~"Attributes vs. Record Components" in this document -and ``Attributes'' in the {\GAP}~4 Reference Manual) -the names `Set' resp.~`Has' are available. - -If the name of a function ends with `NC' then there is another -function with the same name except that the `NC' is missing. -`NC' stands for ``no check''. -When is called then it checks whether its arguments are valid, -and if so then it calls . -The functions `SubgroupNC' and `Subgroup' are a typical example. - -The idea is that the possibly time consuming check of the arguments -can be omitted if one is sure that they are unnecessary. -For example, if an algorithm produces generators of the derived subgroup -of a group then it is guaranteed that they lie in the original group; -`Subgroup' would check this, and `SubgroupNC' omits the check. - -Needless to say, all these rules are not followed slavishly, -for example there is one operation `Zero' instead of two operations -`ZeroOfElement' and `ZeroOfAdditiveGroup'. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Immutable Objects} - -{\GAP}~4 supports ``immutable'' objects. Such objects cannot be -changed, attempting to do so issues an error. Typically attribute -values are immutable, and also the results of those binary arithmetic -operations where both arguments are immutable. -For example, `[1..100]+[1..100]' is a -mutable list and `2 \* Immutable([1..100])' is an immutable -list, both are equal to the (mutable) list `[2,4..200]'. - -There is no way to *make* an immutable object mutable, one can only -get a mutable copy by `ShallowCopy'. The other way round, -`MakeImmutable' makes a (mutable or immutable) object and all its -subobjects immutable; one must be very careful to use `MakeImmutable' -only for those objects that are really newly created, for such objects -the advantage over `Immutable' is that no copy is made. - -More about immutability can be found in Sections ``Immutability'' in -the {\GAP}~4 Tutorial and ``Mutability and Copyability'' in the {\GAP}~4 -Reference Manual. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Copy} - -\indextt{StructuralCopy} -\indextt{ShallowCopy} -The function `Copy' of {\GAP}~3 is not supported in {\GAP}~4. This -function was used to create a copy of its argument with -the properties that and had no subobjects in common and -that if two subobjects of were identical then also the -corresponding subobjects of were identical. - -The possibility of having immutable objects (see~"Immutable Objects") can and -should be used to avoid unnecessary copying. -Namely, given an immutable object one needs to copy it only if one wants -to get a modified object, and in such a situation usually it is -sufficient to use `ShallowCopy', or at least one knows how deep one must -copy in order to do the changes one has in mind. - -For example, suppose you have a matrix group, and you want to -construct a list of matrices by modifying the group generators. This -list of generators is immutable, so you call `ShallowCopy' to get a -mutable list that contains the same matrices. If you only want to -exchange some of them, or to append some other matrices, this shallow -copy is already what you need. So suppose that you are interested in -a list of matrices where some rows are also changed. For that, you -call `ShallowCopy' for the matrices in question, and you get matrices -whose rows can be changed. If you want to change single entries in -some rows, `ShallowCopy' must be called to get mutable copies of these -rows. Note that in all these situations there is no danger to change, -i.e., to destroy the original generators of the matrix group. - -If one needs the facility of the `Copy' function of {\GAP}~3 to get a -copy with the same structure then one can use the new {\GAP}~4 -function `StructuralCopy'. It returns a structural copy that has no -*mutable* subobject in common with its argument. So if -`StructuralCopy' is called with an immutable object then this object -itself is returned, and if `StructuralCopy' is called with a mutable -list of immutable objects then a shallow copy of this list is -returned. - -Note that `ShallowCopy' now is an operation. So if you create your -own type of (copyable) objects then you must define what a shallow -copy of these objects is, and install an appropriate method. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Attributes vs. Record Components} - -In {\GAP}~3, many complex objects were represented via records, for -example all domains. Information about these objects was stored in -components of these records. For the user, this was usually not -relevant, since there were functions for computing information about -the objects in question. For example, if one was interested in the -size of a group then one could call `Size'. - -But since it was guaranteed that the size of a domain was stored -as value of the component `size', it was allowed to access `.size' -if this component was bound, and a check for this was possible via -`IsBound( .size )'. - -In {\GAP}~4, only the access via functions is admissible. One reason -is the following basic rule. - -*From the information that a given {\GAP}~4 object is for example a -domain, one cannot conclude that this object has a certain -representation.* - -For attributes like `Size', {\GAP}~4 provides two related functions, -the *setter* and the *tester* of the attribute, which can be used to -set an attribute value and to check whether the value of an attribute -is already stored for an object (see also ``Attributes'' in the {\GAP}~4 -Reference Manual). For example, if is a domain in {\GAP}~4 then -`HasSize( )' is `true' if the size of is already stored, and -`false' otherwise. In the latter case, if you know that the size of - is then you may store it by `SetSize( , )'. - -Besides the flexibility in the internal representation of objects, -storing information only via function calls has also the advantage -that {\GAP}~4 is able to draw conclusions automatically. For example, -as soon as it is stored that a group is nilpotent, it is also stored -that it is solvable, see Chapters ``Types of Objects'' and -``Method Selection'' in the {\GAP}~4 Reference Manual for the details. - -As a consequence, you cannot put your favourite information into a -domain by assigning it to a new component like -`.myPrivateInfo'. Instead you can introduce a new attribute and -then use its setter, -see Section ``Attributes'' in the {\GAP}~4 Reference Manual. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Different Notions of Generation} - -As in {\GAP}~3, a *domain* in {\GAP}~4 is a structured set. - -The same set can have different structures, for example a field can be -regarded as a ring or as an algebra or vector space over a subfield. - -In {\GAP}~3, however, an object representing a ring did not represent -a field, and an object representing a field did not represent a ring. -One reason for this was that the record component `generators' was -used to denote the appropriate generators of the domain. For a ring -, the component `.generators' was a list of ring generators, and -for a field , `.generators' was a list of field generators. - -{\GAP}~4 cleans this up, -see ``Notions of Generation'' in the {\GAP}~4 Tutorial. It supports -many different notions of generation, for example one can ask for -magma generators of a group or for generators of a field as an additive -group. A subtle but important distinction is that between generators -of an algebra and of an algebra-with-one. - -So the attributes `GeneratorsOfGroup', `GeneratorsOfMagma', -`GeneratorsOfRing', `GeneratorsOfField', `GeneratorsOfVectorSpace', -and so on, replace the access to the `generators' component. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Operations Records} - -Already in {\GAP}~3 there were several functions that were applicable -to many different kinds of objects, for example `Size' could be -applied to any domain, and the binary infix multiplication `*' could -be used to multiply two matrices, an integer with a row vector, or a -permutation with a permutation group. This was implemented as -follows. Functions like `Size' and `*' tried to find out what -situation was described by its arguments, and then it called a more -specific function to compute the desired information. These more -specific functions, let us call them *methods* as they are also called -in {\GAP}~4, were stored in so-called *operations records* of the -arguments. - -For example, every domain in {\GAP}~3 was represented as a record, and -the operations record was stored in the record component `operations'. -If `Size' was called for the domain then the method to compute the -size of the domain was found as value of the `Size' component of the -operations record. - -This was fine for functions taking only one argument, and in principle -it is possible that for those functions an object stored an optimal -method in its operations record. But in the case of more arguments -this is not possible. In a multiplication of two objects in {\GAP}~3, -one had to choose between the methods stored in the operations records -of the arguments, and if for example the method stored for the left -operand was called, this method had to handle all possible right -operands. - -So operations records turned out to be not flexible enough. In -{\GAP}~4, operations records are not supported -%(see~"Compatibility Mode" for a possibility to use your {\GAP}~3 -%code that utilizes operations records, at least to some extent). -A detailed description -of the new mechanism to select methods can be found in -Chapter ``Method Selection'' in the {\GAP}~4 Reference Manual. - -An important point is that the new mechanism allows {\GAP} to take the -relation between arguments into account. So it is possible (and -recommended) to install different methods for different relations -between the arguments. Note that such methods need not do the -extensive argument checking that was necessary in {\GAP}~3, because -most of the checks are done already by the method selection mechanism. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Operations vs. Dispatcher Functions} - -{\GAP}~3 functions like `Size', `CommutatorSubgroup', or -`SylowSubgroup' did mainly call an appropriate method (see~"Operations -Records") after they had checked their arguments. Such functions were -called *dispatchers* in {\GAP}~3. In {\GAP}~4, many dispatchers have -been replaced by *operations*, due to the fact that methods are no -longer stored in operations records (see ``Method Selection'' in -in the {\GAP}~4 Reference Manual for the details). - -Most dispatchers taking only one argument were treated in a special -way in {\GAP}~3, they had the additional task of storing computed -values and using these values in subsequent calls. For example, the -dispatcher `Size' first checked whether the size of the argument was -already stored, and if so then this value was returned; otherwise a -method was called, the value returned by this method was stored in the -argument, and then returned by `Size'. - -In {\GAP}~4, computed values of operations that take one argument -(these operations are called *attributes*) are also stored, only the -mechanism to achieve this has changed, see the sections ``Attributes'' -and ``Properties'' in the {\GAP}~4 Reference Manual. - -So the behaviour of `Size' is the same in {\GAP}~3 and {\GAP}~4. But -note that in {\GAP}~4, it is not possible to access `.size', -see~"Attributes vs. Record Components". As described in~"Operations -Records", {\GAP}~4 does not admit ``bypassing the dispatcher'' by -calling for example `.operations.Size'. This was done in {\GAP}~3 -often for efficiency reasons, but the method selection mechanism of -{\GAP}~4 is fast enough to make this unnecessary. - -If you had written your own dispatchers and put your own methods into -existing operations records then this code will not work in {\GAP}~4. -See ``Creating New Objects'' and ``Method Selection'' in the {\GAP}~4 -Reference Manual for a description of how to define operations and -to install methods. - -Finally, some functions in {\GAP}~3 were hidden in -operations records, e.g., `PermGroupOps.MovedPoints'. -These functions became proper operations in {\GAP}~4. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Parents and Subgroups} - -In {\GAP}~3 there was a strict distinction between parent groups and -subgroups. -The use of the name ``parent'' (instead of ``supergroup'') -was chosen to indicate that the parent of an object was more than just -useful information. -In fact the main reason for the introduction of parents was to provide -a common roof for example for all groups of polycyclic words that -belonged to the same PC-presentation, or for all subgroups of a finitely -presented group (see~"Elements of Finitely Presented Groups"). -A subgroup was never a parent group, and it was possible to create -subgroups only of parent groups. - -In {\GAP}~4 this common roof is provided already by the concept of -*families*, see Section ``Families'' in the {\GAP}~4 Reference Manual. -Thus it is no longer compulsory to use parent groups at all. -On the other hand, parents *may* be used in {\GAP}~4 to provide -information about an object, for example the normalizer of a group in its -parent group may be stored as an attribute value. -Note that there is no restriction on the supergroup that is set to be -the parent, -it is possible to create a subgroup of -any group, this group then being the parent of the new subgroup. -This permits for example chains of subgroups with respective parents, -of arbitrary length. - -As a consequence, the `Parent' command cannot be used in {\GAP}~4 to -test whether the two arguments of `CommutatorSubgroup' fit together, -this is now a question that concerns the relation between the families -of the groups. So the 2-argument version of `Parent' and the now -meaningless function `IsParent' have been abolished. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Homomorphisms vs. General Mappings} - -In {\GAP}~3 there had been a confusion between group homomorphisms and -general mappings, as `GroupHomomorphismByImages' created only a -general mapping that did *not* store whether it was a mapping. This -caused expensive, unwanted, and unnecessary tests whether the mapping -was in fact a group homomorphism. Moreover, the ``official'' -workaround to set some components of the mapping record was quite -unwieldy. - -In {\GAP}~4, `GroupHomomorphismByImages' checks whether the desired -mapping is indeed a group homomorphism; if so then this property is -stored in the returned mapping, otherwise `fail' is returned. If you -want to avoid the checks then you can use -`GroupHomomorphismByImagesNC'. If you want to check whether a general -mapping that respects the group operations is really a group -homomorphism, you can construct it via `GroupGeneralMappingByImages' -and then call `IsGroupHomomorphism' for it. (Note that -`IsGroupHomomorphism' returns `true' if and only if both -`IsGroupGeneralMapping' and `IsMapping' do, so one does in fact check -`IsMapping' in this case.) - -There is *no* function `IsHomomorphism' in {\GAP}~4, -since there are several different operations with respect to which a -mapping can be a homomorphism. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Homomorphisms vs. Factor Structures} - -If $F$ is a factor structure of $G$, with kernel $N$, complete -information about the connection between $F$ and $G$ is provided by -the *natural homomorphism*. - -In {\GAP}~3, the ``official way'' to construct this natural homomorphism -was to create first the factor structure $F$, and then to call -`NaturalHomomorphism' with the arguments $G$ and $F$. -For that, the data necessary to compute the homomorphism was stored in -$F$ when $F$ was constructed. - -In {\GAP}~4, factor structures are not treated in a special way, -in particular they do not store information about a homomorphism. -Instead, the more natural way is taken to construct the natural -homomorphism from $G$ and $N$ by `NaturalHomomorphismByNormalSubgroup' -if $N$ is a normal subgroup of the group $G$, -or by `NaturalHomomorphismByIdeal' if $N$ is an ideal in the ring $G$. -The factor $F$ can then be accessed as the image of this homomorphism, -and of course $G$ is the preimage and $N$ is the kernel. - -Note that {\GAP}~4 does not guarantee anything about the representation -of the factor $F$, it may be a permutation group or a polycyclically -presented group or another kind of group. -Also note that a natural homomorphism need not be surjective. - -A consequence of this change is that {\GAP}~4 does *not* allow you to -construct a natural homomorphism from the groups $G$ and $F$. - -The other common type of homomorphism in {\GAP} 3, ``operation -homomorphisms'', have been replaced (just a name change) by *action -homomorphisms*, which are handled in a similar fashion. That is, an -action homomorphism is constructed from an acting group, an action -domain, and a function describing the operation. The permutation -group arising by the induced action is then the image of this -operation homomorphism. - -The {\GAP}~3 function `Operation' is still supported, under the name `Action', -but from the original group and the result of `Action' it is not -possible to construct the action homomorphism. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Isomorphisms vs. Isomorphic Structures} - -In {\GAP}~3, a different representation of a group could be obtained by -calling `AgGroup' to get an isomorphic polycyclically presented group, -`PermGroup' to get an isomorphic permutation group, and so on. -The returned objects stored an isomorphism in the record component -`bijection'. - -For the same reason as in~"Homomorphisms vs. Factor Structures", -{\GAP}~4 puts emphasis on the isomorphism, -and the isomorphic object in the desired representation can be accessed -as its image. -So you can call `IsomorphismPcGroup' or `IsomorphismPermGroup' in order -to get an isomorphism to a polycyclically presented group or a -permutation group, respectively, and then call `Image' to get the -isomorphic group. - -Note that the image of an action homomorphism with trivial kernel is -also an isomorphic permutation group, but an action homomorphism need -not be surjective, since it may be easier to define it into the full -symmetric group. - -Further note that in {\GAP}~3, a usual application of isomorphisms to -polycyclically presented groups was to utilize the usually more -effective algorithms for solvable groups. However, the new concept of -polycyclic generating systems in {\GAP}~4 makes it possible to apply -these algorithms to arbitrary solvable groups, independent of the -representation. For example, {\GAP}~4 can handle polycyclic -generating systems of solvable permutation groups. So in many cases, -a change of the representation for efficiency reasons may be not -necessary any longer. - -In general `IsomorphismFpGroup' will define a presentation on generators -chosen by the algorithm. The corresponding elements of the original -group can be obtained by the command -\begintt -gens:=List(GeneratorsOfGroup(Image(isofp)),i->PreImagesRepresentative(isofp,i)); -\endtt -If a presentation in the given generators is needed, the command -`IsomorphismFpGroupByGenerators(, )' will produce one. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Elements of Finitely Presented Groups} - -Strictly speaking, {\GAP}~3 did not support elements of finitely -presented groups. Instead, the ``words in abstract generators'' of -the underlying free groups were (mis)used. This caused problems -whenever calculations with elements were involved, the most obvious -ones being wrong results of element comparisons. Also functions -that should in principle work for any group were not applicable to -finitely presented groups. In effect, a finitely presented group had -to be treated in a special way in {\GAP}~3. - -{\GAP}~4 distinguishes free groups and their elements from finitely -presented groups and their elements. Comparing two elements of a -finitely presented group will yield either the correct result or no -result at all. - -Note that in {\GAP}~4, the arithmetic and comparison operations for -group elements do not depend on a context provided by a group that -contains the elements. In particular, in {\GAP}~4 it is not -meaningful to call `Order( , )' for a group and an element -. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Polynomials} - -In {\GAP}~3, polynomials were defined over a field. So a polynomial over -`GF(3)' was different from a polynomial over `GF(9)', even if the -coefficients were exactly the same. - -{\GAP}~4 defines polynomials only over a characteristic. This makes it -possible for example to multiply a polynomial over `GF(3)' with a polynomial -over `GF(9)' without the need to convert the former to the larger field. - -However it has an effect on the result of `DefaultRing' for polynomials: -In {\GAP}~3 the default ring for a polynomial was the polynomial ring of the -field over which the polynomial was defined. In {\GAP}~4 no field is -associated, so (to avoid having to define the algebraic closure as the only -other sensible alternative) the default ring of a polynomial is the -`DefaultRing' of its coefficients. - -This has an effect on `Factors': If no ring is given, a polynomial is -factorized over its `DefaultRing' and so `Factors()' -might return different results. - -To be safe from this problem, if you are not working over prime fields, -rather call `Factors(,)' with the appropriate polynomial ring -and change your code accordingly. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{The Info Mechanism} - -Sometimes it is useful to get information about the progress of a -calculation. -Many {\GAP} functions contain statements to display such information -under certain conditions. - -In {\GAP}~3, these statements were calls to functions such as -`InfoGroup1' or `InfoGroup2', and if the user assigned `Print' to -these variables then this had the effect to switch on the printing of -information. -`InfoGroup2' was used for more detailed information than `InfoGroup1'. -One could switch off the printing again by assigning `Ignore' to the -variables, and `Ignore' was also the default value. - -{\GAP}~4 uses one function `Info' for the same purpose, -which is a function that takes as first argument an *info class* such as -`InfoGroup', as second argument an *info level*, and the print statements -as remaining arguments. -The level of an info class is set to by calling -`SetInfoLevel( , )'. -An `Info' statement is printed only if its second argument is smaller than -or equal to the current info level. -For example, -\beginexample -gap> test:= function( obj ) -> Info( InfoGroup, 2, "This is useful, isn't it?" ); -> return obj; -> end;; -gap> test( 1 ); -1 -gap> SetInfoLevel( InfoGroup, 2 ); -gap> test( 1 ); -#I This is useful, isn't it? -1 -\endexample - -As in {\GAP}~3, if an info statement is ignored then its arguments are -not evaluated. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Debugging} - -\indextt{Backtrace} -\indextt{DownEnv} -\indextt{Where} -If {\GAP}~4 runs into an error or is interrupted, -it enters a break loop. -The command `Where( )', which replaces `Backtrace' of {\GAP}~3, -can be used to display lines of information about the current -function call stack. - -As in {\GAP}~3, access is only possible to the variables of the current -level in the function stack, -but in {\GAP}~4 the function `DownEnv', with a positive or negative -integer as argument, permits one to step down or up in the -stack. - -When interrupting, the first line printed by `Where' actually may be -one level higher, as the following example shows -\begintt -gap> OnBreak := function() Where(0); end;; # eliminate back-tracing on -gap> # entry to break loop -gap> test:= function( n ) -> if n > 3 then Error( "!\n" ); fi; test( n+1 ); end;; -gap> test( 1 ); -Error, ! -Entering break read-eval-print loop ... -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue -brk> Where(); - called from -test( n + 1 ); called from -test( n + 1 ); called from -test( n + 1 ); called from -( ) called from read-eval-loop -brk> n; -4 -brk> DownEnv(); -brk> n; -3 -brk> Where(); - called from -test( n + 1 ); called from -test( n + 1 ); called from -( ) called from read-eval-loop -brk> DownEnv( 2 ); -brk> n; -1 -brk> Where(); - called from -( ) called from read-eval-loop -brk> DownEnv( -2 ); -brk> n; -3 -brk> quit; -gap> OnBreak := Where;; # restore OnBreak to its default value -\endtt - -For purposes of debugging, it can be helpful sometimes, to see what -information is stored within an object. In {\GAP}~3 this was possible using -`RecFields' because the objects in question were represented via records. -For component objects, {\GAP}~4 permits the same by -`NamesOfComponents( )', which will list all components present. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% \Section{Compatibility Mode} -% -% For users who want to use {\GAP}~3 code with as little changes as -% possible, a compatibility mode is provided by {\GAP}~4. -% This mode must be turned on explicitly by the user. -% -% It should be noted that this compatibility mode has not been tested -% thoroughly. -% -% The compatibility mode can be turned on by loading some of the following -% files with `ReadLib'. -% The different files address different aspects of compatibility. -% -% \beginitems -% `compat3a.g' & -% makes some {\GAP}~3 function names available that were changed -% in {\GAP}~4, -% and provides code for some {\GAP}~3 features that were -% deliberately left out from the {\GAP}~4 library. -% For example, -% almost all variable names concerning character theory that are -% mentioned in the {\GAP}~3 manual, -% such as `CharTable' and `SubgroupFusions', -% are available after `compat3a.g' has been read; -% the only exceptions are names of operations records. -% -% `compat3b.g' & -% implements the availability of ``components'' of domains; -% besides components that have no meaning for the rest of the {\GAP}~4 -% library, such as `.myInfo', there are components associated to -% attributes; for example `.size' is redirected to the call of the -% attribute `Size', `IsBound( .size )' to the call of its tester, -% and `.size:= ' to the call of its setter. -% (An important special case is the component `operations', see below.) -% -% `compat3c.g' & -% permits you to implement your own elements represented as records, -% and using operations records to provide a `Print' method and -% the basic arithmetic operations. -% When using operations records, it is probably a good idea to -% use *immutable* operations records; for example, if the results -% of arithmetic operations are records with operations records then -% this avoids to create shallow copies of the operations records -% in the call to `Immutable' for the results. -% \enditems -% -% The following features are accessible only via starting {\GAP} with -% the command line option `-O' and may damage some features of {\GAP}~4 -% permanently for the current session. -% -% With this option, also the files listed above are read automatically. -% -% \beginitems -% `compat3d.g' & -% provides some {\GAP}~3 functions like `Domain', simulates the -% {\GAP}~3 behaviour of `IsString' (to convert a list to string -% representation if possible), and replaces `fail' by `false'; -% these changes destroy parts of the functionality of {\GAP}~4. -% \enditems -% -% Some words concerning the simulation of operations records may be -% necessary. -% -% The operations records of the {\GAP}~3 library, such as `DomainOps' -% and `GroupOps', are available *only* for access to their components, -% whose values are {\GAP}~4 operations; for example, the value of both -% `DomainOps.Size' and `GroupOps.Size' is the operation `Size'. So it -% is *not* safely possible to delegate from a `Size' method in another -% operations record to `DomainOps.Size'. Also it is not possible to -% change these predefined operations records. -% -% If one wants to install individual methods for a given object -% via the mechanism of operations records then one can construct a new -% operations record with `OperationsRecord', assign the desired methods -% to components of this record, and then assign the operations record to -% `.operations'. Whenever an operation that is associated with a -% component of the operations record is called with as first -% argument, the value of is chosen as the method. -% -% In the case of the binary operations `=', `\<', `+', `-', `*', `/', -% `Comm', and `LeftQuotient', -% this also happens if is the right-hand argument. -% As in {\GAP}~3, if both arguments of one of the above binary operations -% have operations records containing a function for this operation, -% then the function in the operations record of the right-hand argument -% is chosen. -% -% We give a small example how the compatibility mode works. -% -% Suppose we want to deal with new objects that are derived from known -% field elements by distorting their multiplication. Namely, let $a'$ -% and $b'$ be the new objects corresponding to the field elements $a$, -% $b$, and define $a' \* b' = a b - a - b + 2$. -% -% In {\GAP}~3, this problem was solved by representing each new object -% by a record that stored the corresponding ``old'' object and an -% operations record, where the latter was a record containing the -% functions applicable to the new object. After the library file -% `compat3c.g' has been read, we can use this construction of the -% operations record and of the new objects. Note that operations -% records must be created with the function `OperationsRecord' (this was -% also the norm in {\GAP}~3), starting with an empty record would not work. -% For our intended application, we thus start with the following two -% lines of code. -% -% \begintt -% gap> ReadLib( "compat3c.g" ); -% gap> MyOps:= OperationsRecord( "MyOps" );; -% HasMyOps := NewFilter( "HasMyOps" ); -% \endtt -% -% In order to make the translation from {\GAP}~3 code to {\GAP}~4 -% easier, {\GAP} prints the definition of filters associated with -% operations records and the method installations for operations -% corresponding to components of the operations records. The output -% line printed by {\GAP} after the call of `OperationsRecord' is one -% such case. -% -% Now we add our multiplication function to the operations record, -% and again {\GAP}~4 prints a translation to {\GAP}~4 code. -% -% \begintt -% gap> MyOps.\* := function( a, b ) -% > return rec( x:= a.x * b.x - a.x - b.x + 2, -% > operations := MyOps ); -% > end;; -% # If the following method installation matches the requirements -% # of the operation `PROD' then `InstallMethod' should be used. -% # It might be useful to replace the rank `SUM_FLAGS' by `0'. -% InstallOtherMethod( PROD, -% "for object with `MyOps' as first argument", -% true, -% [ HasMyOps, IsObject ], SUM_FLAGS, -% MyOps.\* ); -% -% # For binary infix operators, a second method is installed -% # for the case that the object with `MyOps' is the right operand; -% # since this case has higher priority in GAP 3, the method is -% # installed with higher rank `SUM_FLAGS + 1'. -% InstallOtherMethod( PROD, -% "for object with `MyOps' as second argument", -% true, -% [ IsObject, HasMyOps ], SUM_FLAGS + 1, -% MyOps.\* ); -% \endtt -% -% Let us look how this installation works. -% -% \begintt -% gap> a:= rec( x:= 3, operations:= MyOps ); -% rec( x := 3, operations := MyOps ) -% gap> b:= rec( x:= 5, operations:= MyOps ); -% rec( x := 5, operations := MyOps ) -% gap> a * b; -% rec( x := 9, operations := MyOps ) -% \endtt -% -% (In more complicated cases, we might run into problems, but this was -% already the case in {\GAP}~3. For example, suppose we want to support -% the multiplication of two operands having different operations -% records; then it is not clear which of the two multiplication -% functions is to be chosen, and in {\GAP}~3, the only way out was to -% change the multiplication functions, in order to make them aware of -% such situations.) -% -% If we are now interested to translate the code to {\GAP}~4 in the -% sense that no compatibility mode is needed, we can use what {\GAP}~4 -% has printed above. (The same example is dealt with in Section ``An -% Example -- Designing Arithmetic Operations'' in the {\GAP}~4 Reference -% Manual.) -% -% The objects will no longer be records with `operations' component. -% Instead of records we may use so-called component objects -% with record-like access to components, -% and instead of the `operations' component, we give the objects a -% type that has the filter `HasMyOps' set. -% \begintt -% HasMyOps := NewFilter( "HasMyOps" ); -% MyType := NewType( NewFamily( "MyFamily" ), -% HasMyOps and IsComponentObjectRep ); -% \endtt -% (More about families and representations in this context can be found -% in the same chapter of the {\GAP}~4 Reference Manual mentioned above.) -% -% The next step is to write a function that creates a new object. -% It may look as follows. -% \begintt -% MyObject := function( val ) -% return Objectify( MyType, rec( x:= val ) ); -% end; -% \endtt -% -% The multiplication function shall return an object with the -% filter `HasMyOp', so we change it as follows. -% \begintt -% gap> MyMult := function( a, b ) -% > return MyObject( x:= a!.x * b!.x - a!.x - b!.x + 2 ); -% > end;; -% \endtt -% Note that the component access for these objects -% works via `!.' instead of `.'; -% further note that no operations record needs to appear here, -% the filter takes its role. -% -% Finally, we install the multiplication for at least one argument -% with the new filter, as had been printed by {\GAP}~4 in the -% session shown above. -% \begintt -% InstallOtherMethod( PROD, -% "for object with `MyOps' as first argument", -% true, -% [ HasMyOps, IsObject ], 0, -% MyMult ); -% -% InstallOtherMethod( PROD, -% "for object with `MyOps' as second argument", -% true, -% [ IsObject, HasMyOps ], 1, -% MyMult ); -% \endtt -% And now the example works (again). -% \begintt -% gap> a:= MyObject( 3 ); -% -% gap> b:= MyObject( 5 ); -% -% gap> a * b; -% -% gap> last!.x -% 9 -% \endtt -% -% We may install a method to print our objects in a nice way; -% we could have done this for the operations record `MyOps' -% in the compatibility mode, -% the printed output would look similar to the following. -% \begintt -% InstallOtherMethod( PRINT_OBJ, -% "for object with `MyOps' as first argument", -% true, -% [ HasMyOps ], 0, -% function( obj ) Print( "MyObject( ", obj!.x, " )" ); end ); -% \endtt -% -% Now the example behaves as follows. -% \begintt -% gap> a; b; a * b; -% MyObject( 3 ) -% MyObject( 5 ) -% MyObject( 9 ) -% \endtt -% -% Maybe now we want to improve the installation. -% The multiplication function we want to use is apparently -% thought only for the case that *both* operands have -% the filter `HasMyOps' (and a component `x'). -% So it is reasonable to replace the two methods for -% the multiplication by one method for which both arguments -% are required to have the filter. -% \begintt -% InstallOtherMethod( PROD, -% "for two objects with `MyOps'", -% true, -% [ HasMyOps, HasMyOps ], 0, -% MyMult ); -% \endtt -% -% At first sight, the {\GAP}~4 approach seems to be much more -% complicated. -% But the last example shows that in {\GAP}~4, -% each method can be installed more specifically for the appropriate -% situation. -% Moreover, it is for example possible to install a method -% for the multiplication of an integer and a `HasMyOps' object; -% note that --contrary to the situation in {\GAP}~3-- -% such a method is independent from already existing methods -% in the sense that these need not be changed when -% new functionality is added. -% -% Another example that uses this part of the compatibility mode can be -% found in the file `tst/compat3.tst' of the {\GAP}~4 distribution. - -\EndOfBook - diff --git a/doc/tut/migrat.xml b/doc/tut/migrat.xml deleted file mode 100644 index cf182c4fc2..0000000000 --- a/doc/tut/migrat.xml +++ /dev/null @@ -1,1227 +0,0 @@ - - - - - - - - -Migrating to &GAP; 4 - -This chapter is intended to give users who have experience with &GAP; 3 -some information about what has changed in &GAP; 4. -

-In particular, it informs about changed command line options -(see ), -the new global variable fail (see ), -some functions that have changed their behaviour -(see ) or their names -(see ), -and some conventions used for variable names (see ). -

-Then the new concepts of &GAP; 4 are sketched, -first that of mutability or immutability (see ), -with the explanation of related changes in functions that copy objects -(see ), -then the concepts of operations and method selection, which are compared -with the use of operations records in &GAP; 3 -(see , , -and ). -

-More local changes affect the concepts of notions of generation -(see ), -of parents (see ), -of homomorphisms (see , -, -and ), -how elements in finitely presented groups are treated -(see ), -how information about progress of computations can be obtained -(see ), -and how one gets information in a break loop -(see ). -

-While a &GAP; 3 compatibility mode is provided -(see ), -its use will disable some of the new features of &GAP; 4. -Also it certainly can only try to provide partial compatibility. -

-For a detailed explanation of the new features and concepts of &GAP; 4, -see the manual Programming in GAP. - - - -

-Changed Command Line Options - -In &GAP; 4, the -l option is used to specify the root directory -(see ) -of the &GAP; distribution, -which is the directory containing the lib and doc subdirectories. -Note that in &GAP; 3 this option was used to specify the path to the -lib directory. -

-The -h option of &GAP; 3 has been removed, -the path(s) for the documentation are deduced automatically in &GAP; 4. -

-The option -g is now used to print information only about full garbage -collections. -The new option -g -g generates information about partial -garbage collections too. - -

- - - -
-Fail - -There is a new global variable -fail instead of false -

- - - -in &GAP; 4. -It is intended as a return value of a function for the case that it -could not perform its task. -For example, Inverse returns fail if it is called with a singular -matrix, and Position returns fail if the second argument is not -contained in the list given as first argument. -

-&GAP; 3 handled such situations by either signalling an error, -for example if it was asked for the inverse of a singular matrix, -or by (mis)using false as return value, as in the example Position. -Note that in the first example, in &GAP; 3 it was necessary to check -the invertibility of a matrix before one could safely ask for its -inverse, which meant that roughly the same work was done twice. - - - -

- - - -
-Changed Functionality - -Some functions that were already available in &GAP; 3 behave -differently in &GAP; 4. This section lists them. -

- - - -The &GAP; 3 manual promised that pnt would be the first entry of the -resulting orbit. This was wrong already there in a few cases, therefore -&GAP; 4 does not promise anything about the ordering of points in an orbit. - - -

- - - -only takes the element g and computes its multiplicative order. -Calling Order with two arguments is permitted only in the -&GAP; 3 compatibility mode, see . -(Note that it does not make sense anymore to specify a group as -first argument w.r.t. which the order of the second argument shall -be computed, see .) - - -

- - - -If obj is not contained in the list list then fail is returned -in &GAP; 4 (see ), whereas false was returned in &GAP; 3. - - -

- - - -In &GAP; 3, this function took either two or three arguments, -the optional argument K being a subgroup of G that stabilizes prop -in the sense that for any element g in G, -either all elements or no element in the coset g * K have the -property prop. -

-The &GAP; 4 function ElementProperty, however, -takes between two and four arguments, -and the subgroup K known from &GAP; 3 has to be entered as the fourth -argument not the third. -(The third argument in the &GAP; 4 function denotes a subgroup U -stabilizing prop in the sense that either all elements or no element -in right cosets U * g have the property prop.) -

-(This discrepancy was discovered only in March 2002, -short before the release of &GAP; 4.3.) - - -

- - - -Objects may appear on the screen in a different way, -depending on whether they are printed by the read eval print loop -or by an explicit call of Print. -The reason is that the read eval print loop calls the operation ViewObj -and not PrintObj, whereas Print calls PrintObj for each of its -arguments. -This permits the installation of methods for printing objects in a short form -in the read eval print loop while retaining Print to display -the object completely. -See also Section . -

-(PrintObj is installed as standard method ViewObj, so it is -not really necessary to have a ViewObj method for an object.) - - -

- - - -In &GAP; 3, PrintTo could be (mis)used to redirect the text -printed by a function (that is, not only the output of a function) -to a file by entering the function call as second argument. -This was used mainly in order to avoid many calls of AppendTo. -In &GAP; 4, this feature has disappeared. -One can use streams (see Chapter ) -instead in order to write files efficiently. - - - -

- - - -
-Changed Variable Names - -AgGroup -ApplyFunc -Backtrace -CharTable -Denominator -DepthVector -Elements -IsBijection -IsFunc -IsMat -IsRec -IsSet -LengthWord -NOfCyc -Numerator -RandomInvertableMat -RecFields -X - -Some functions have changed their name without changing the -functionality. -A -- probably incomplete -- list follows -

- -

-See Section  for a way to make the old names -available again. - -

- - - -
-Naming Conventions - -The way functions are named has been unified in &GAP; 4. -This might help to memorize or even guess names of library functions. -

-If a variable name consists of several words then the first -letter of each word is capitalized. -

-If the first part of the name of a function is a verb then the function -may modify its argument(s) but does not return anything, -for example Append appends the list given as second argument to the -list given as first argument. -Otherwise the function returns an object without changing the arguments, -for example Concatenation returns the concatenation of the lists -given as arguments. -

-If the name of a function contains the word By then the return value is -thought of as built in a certain way from the parts given as arguments. -For example, GroupByGenerators returns a group built from its group -generators, and creating a group as a factor group of a given group -by a normal subgroup can be done by taking the image of -NaturalHomomorphismByNormalSubgroup -(see also ). -Other examples of By functions are GroupHomomorphismByImages and -UnivariateLaurentPolynomialByCoefficients. -

-If the name of a function contains the word Of then the return value is -thought of as information deduced from the arguments. -Usually such functions are attributes -(see  in this Tutorial and ). -Examples are GeneratorsOfGroup, which returns a list of generators for -the group entered as argument, or DiagonalOfMat. -

-For the setter and tester functions of an attribute attr -(see  in this Tutorial -and ) -the names Setattr resp. Hasattr are available. -

-If the name of a function fun1 ends with NC then there is another -function fun2 with the same name except that the NC is missing. -NC stands for no check. -When fun2 is called then it checks whether its arguments are valid, -and if so then it calls fun1. -The functions SubgroupNC and Subgroup are a typical example. -

-The idea is that the possibly time consuming check of the arguments -can be omitted if one is sure that they are unnecessary. -For example, if an algorithm produces generators of the derived subgroup -of a group then it is guaranteed that they lie in the original group; -Subgroup would check this, and SubgroupNC omits the check. -

-Needless to say, all these rules are not followed slavishly, -for example there is one operation Zero instead of two operations -ZeroOfElement and ZeroOfAdditiveGroup. - -

- - - -
-Immutable Objects - -&GAP; 4 supports immutable objects. Such objects cannot be -changed, attempting to do so issues an error. Typically attribute -values are immutable, and also the results of those binary arithmetic -operations where both arguments are immutable, -see Section . -For example, [ 1 .. 100 ] + [ 1 .. 100 ] is a -mutable list and 2 * Immutable( [ 1 .. 100 ] ) is an immutable -list, both are equal to the (mutable) list [ 2, 4 .. 200 ]. -

-There is no way to make an immutable object mutable, one can only -get a mutable copy by ShallowCopy. The other way round, -MakeImmutable makes a (mutable or immutable) object and all its -subobjects immutable; one must be very careful to use MakeImmutable -only for those objects that are really newly created, for such objects -the advantage over Immutable is that no copy is made. -

-More about immutability can be found in Sections  in -this tutorial and . - -

- - - -
-Copy - -StructuralCopy -ShallowCopy -The function Copy of &GAP; 3 is not supported in &GAP; 4. This -function was used to create a copy cop of its argument obj with -the properties that cop and obj had no subobjects in common and -that if two subobjects of obj were identical then also the -corresponding subobjects of cop were identical. -

-The possibility of having immutable objects (see ) can and -should be used to avoid unnecessary copying. -Namely, given an immutable object one needs to copy it only if one wants -to get a modified object, and in such a situation usually it is -sufficient to use ShallowCopy, or at least one knows how deep one must -copy in order to do the changes one has in mind. -

-For example, suppose you have a matrix group, and you want to -construct a list of matrices by modifying the group generators. This -list of generators is immutable, so you call ShallowCopy to get a -mutable list that contains the same matrices. If you only want to -exchange some of them, or to append some other matrices, this shallow -copy is already what you need. So suppose that you are interested in -a list of matrices where some rows are also changed. For that, you -call ShallowCopy for the matrices in question, and you get matrices -whose rows can be changed. If you want to change single entries in -some rows, ShallowCopy must be called to get mutable copies of these -rows. Note that in all these situations there is no danger to change, -i.e., to destroy the original generators of the matrix group. -

-If one needs the facility of the Copy function of &GAP; 3 to get a -copy with the same structure then one can use the new &GAP; 4 -function StructuralCopy. It returns a structural copy that has no -mutable subobject in common with its argument. So if -StructuralCopy is called with an immutable object then this object -itself is returned, and if StructuralCopy is called with a mutable -list of immutable objects then a shallow copy of this list is -returned. -

-Note that ShallowCopy now is an operation. So if you create your -own type of (copyable) objects then you must define what a shallow -copy of these objects is, and install an appropriate method. - -

- - - -
-Attributes vs. Record Components - -In &GAP; 3, many complex objects were represented via records, for -example all domains. Information about these objects was stored in -components of these records. For the user, this was usually not -relevant, since there were functions for computing information about -the objects in question. For example, if one was interested in the -size of a group then one could call Size. -

-But since it was guaranteed that the size of a domain D was stored -as value of the component size, it was allowed to access D.size -if this component was bound, and a check for this was possible via -IsBound( D.size ). -

-In &GAP; 4, only the access via functions is admissible. One reason -is the following basic rule. -

-From the information that a given &GAP; 4 object is for example a -domain, one cannot conclude that this object has a certain -representation. -

-For attributes like Size, &GAP; 4 provides two related functions, -the setter and the tester of the attribute, which can be used to -set an attribute value and to check whether the value of an attribute -is already stored for an object (see also ). For example, if D is a domain in &GAP; 4 then -HasSize( D ) is true if the size of D is already stored, and -false otherwise. In the latter case, if you know that the size of -D is size then you may store it by SetSize( D, size ). -

-Besides the flexibility in the internal representation of objects, -storing information only via function calls has also the advantage -that &GAP; 4 is able to draw conclusions automatically. For example, -as soon as it is stored that a group is nilpotent, it is also stored -that it is solvable, see Chapters  and  -for the details. -

-As a consequence, you cannot put your favourite information into a -domain D by assigning it to a new component like -D.myPrivateInfo. Instead you can introduce a new attribute and -then use its setter, see . - -

- - - -
-Different Notions of Generation - -As in &GAP; 3, a domain in &GAP; 4 is a structured set. -

-The same set can have different structures, for example a field can be -regarded as a ring or as an algebra or vector space over a subfield. -

-In &GAP; 3, however, an object representing a ring did not represent -a field, and an object representing a field did not represent a ring. -One reason for this was that the record component generators was -used to denote the appropriate generators of the domain. For a ring -R, the component R.generators was a list of ring generators, and -for a field F, F.generators was a list of field generators. -

-&GAP; 4 cleans this up, see . It supports -many different notions of generation, for example one can ask for -magma generators of a group or for generators of a field as an additive -group. A subtle but important distinction is that between generators -of an algebra and of an algebra-with-one. -

-So the attributes GeneratorsOfGroup, GeneratorsOfMagma, -GeneratorsOfRing, GeneratorsOfField, GeneratorsOfVectorSpace, -and so on, replace the access to the generators component. - -

- - - -
-Operations Records - -Already in &GAP; 3 there were several functions that were applicable -to many different kinds of objects, for example Size could be -applied to any domain, and the binary infix multiplication * could -be used to multiply two matrices, an integer with a row vector, or a -permutation with a permutation group. This was implemented as -follows. Functions like Size and * tried to find out what -situation was described by its arguments, and then it called a more -specific function to compute the desired information. These more -specific functions, let us call them methods as they are also called -in &GAP; 4, were stored in so-called operations records of the -arguments. -

-For example, every domain in &GAP; 3 was represented as a record, and -the operations record was stored in the record component operations. -If Size was called for the domain then the method to compute the -size of the domain was found as value of the Size component of the -operations record. -

-This was fine for functions taking only one argument, and in principle -it is possible that for those functions an object stored an optimal -method in its operations record. But in the case of more arguments -this is not possible. In a multiplication of two objects in &GAP; 3, -one had to choose between the methods stored in the operations records -of the arguments, and if for example the method stored for the left -operand was called, this method had to handle all possible right -operands. -

-So operations records turned out to be not flexible enough. -In &GAP; 4, operations records are not supported -(see  for a possibility -to use your &GAP; 3 code that utilizes operations records, -at least to some extent). -A detailed description -of the new mechanism to select methods can be found in -Chapter . -

-An important point is that the new mechanism allows &GAP; to take the -relation between arguments into account. So it is possible (and -recommended) to install different methods for different relations -between the arguments. Note that such methods need not do the -extensive argument checking that was necessary in &GAP; 3, because -most of the checks are done already by the method selection mechanism. - -

- - - -
-Operations vs. Dispatcher Functions - -&GAP; 3 functions like Size, CommutatorSubgroup, or -SylowSubgroup did mainly call an appropriate method -(see ) -after they had checked their arguments. -Such functions were -called dispatchers in &GAP; 3. In &GAP; 4, many dispatchers have -been replaced by operations, due to the fact that methods are no -longer stored in operations records (see  for the details). -

-Most dispatchers taking only one argument were treated in a special -way in &GAP; 3, they had the additional task of storing computed -values and using these values in subsequent calls. For example, the -dispatcher Size first checked whether the size of the argument was -already stored, and if so then this value was returned; otherwise a -method was called, the value returned by this method was stored in the -argument, and then returned by Size. -

-In &GAP; 4, computed values of operations that take one argument -(these operations are called attributes) are also stored, only the -mechanism to achieve this has changed, see  -and . -

-So the behaviour of Size is the same in &GAP; 3 and &GAP; 4. But -note that in &GAP; 4, it is not possible to access D.size, -see . -As described in , -&GAP; 4 does not admit bypassing the dispatcher by -calling for example D.operations.Size. This was done in &GAP; 3 -often for efficiency reasons, but the method selection mechanism of -&GAP; 4 is fast enough to make this unnecessary. -

-If you had written your own dispatchers and put your own methods into -existing operations records then this code will not work in &GAP; 4. -See  -and  -for a description of how to define operations -and to install methods. -

-Finally, some functions in &GAP; 3 were hidden in -operations records, e.g., PermGroupOps.MovedPoints. -These functions became proper operations in &GAP; 4. - -

- - - -
-Parents and Subgroups - -In &GAP; 3 there was a strict distinction between parent groups and -subgroups. -The use of the name parent (instead of supergroup) -was chosen to indicate that the parent of an object was more than just -useful information. -In fact the main reason for the introduction of parents was to provide -a common roof for example for all groups of polycyclic words that -belonged to the same PC-presentation, or for all subgroups of a finitely -presented group (see ). -A subgroup was never a parent group, and it was possible to create -subgroups only of parent groups. -

-In &GAP; 4 this common roof is provided already by the concept of -families, see . -Thus it is no longer compulsory to use parent groups at all. -On the other hand, parents may be used in &GAP; 4 to provide -information about an object, for example the normalizer of a group in its -parent group may be stored as an attribute value. -Note that there is no restriction on the supergroup that is set to be -the parent, -it is possible to create a subgroup of -any group, this group then being the parent of the new subgroup. -This permits for example chains of subgroups with respective parents, -of arbitrary length. -

-As a consequence, the Parent command cannot be used in &GAP; 4 to -test whether the two arguments of CommutatorSubgroup fit together, -this is now a question that concerns the relation between the families -of the groups. So the 2-argument version of Parent and the now -meaningless function IsParent have been abolished. - -

- - - -
-Homomorphisms vs. General Mappings - -In &GAP; 3 there had been a confusion between group homomorphisms and -general mappings, as GroupHomomorphismByImages created only a -general mapping that did not store whether it was a mapping. This -caused expensive, unwanted, and unnecessary tests whether the mapping -was in fact a group homomorphism. Moreover, the official -workaround to set some components of the mapping record was quite -unwieldy. -

-In &GAP; 4, GroupHomomorphismByImages checks whether the desired -mapping is indeed a group homomorphism; if so then this property is -stored in the returned mapping, otherwise fail is returned. If you -want to avoid the checks then you can use -GroupHomomorphismByImagesNC. If you want to check whether a general -mapping that respects the group operations is really a group -homomorphism, you can construct it via GroupGeneralMappingByImages -and then call IsGroupHomomorphism for it. (Note that -IsGroupHomomorphism returns true if and only if both -IsGroupGeneralMapping and IsMapping do, so one does in fact check -IsMapping in this case.) -

-There is no function IsHomomorphism in &GAP; 4, -since there are several different operations with respect to which a -mapping can be a homomorphism. - -

- - - -
-Homomorphisms vs. Factor Structures - -If F is a factor structure of G, with kernel N, complete -information about the connection between F and G is provided by -the natural homomorphism. -

-In &GAP; 3, the official way to construct this natural homomorphism -was to create first the factor structure F, and then to call -NaturalHomomorphism with the arguments G and F. -For that, the data necessary to compute the homomorphism was stored in -F when F was constructed. -

-In &GAP; 4, factor structures are not treated in a special way, -in particular they do not store information about a homomorphism. -Instead, the more natural way is taken to construct the natural -homomorphism from G and N by NaturalHomomorphismByNormalSubgroup -if N is a normal subgroup of the group G, -or by NaturalHomomorphismByIdeal if N is an ideal in the ring G. -The factor F can then be accessed as the image of this homomorphism, -and of course G is the preimage and N is the kernel. -

-Note that &GAP; 4 does not guarantee anything about the representation -of the factor F, it may be a permutation group or a polycyclically -presented group or another kind of group. -Also note that a natural homomorphism need not be surjective. -

-A consequence of this change is that &GAP; 4 does not allow you to -construct a natural homomorphism from the groups G and F. -

-The other common type of homomorphism in &GAP; 3, operation -homomorphisms, have been replaced (just a name change) by action -homomorphisms, which are handled in a similar fashion. That is, an -action homomorphism is constructed from an acting group, an action -domain, and a function describing the operation. The permutation -group arising by the induced action is then the image of this -operation homomorphism. -

-The &GAP; 3 function Operation is still supported, under the name Action, -but from the original group and the result of Action it is not -possible to construct the action homomorphism. - -

- - - -
-Isomorphisms vs. Isomorphic Structures - -In &GAP; 3, a different representation of a group could be obtained by -calling AgGroup to get an isomorphic polycyclically presented group, -PermGroup to get an isomorphic permutation group, and so on. -The returned objects stored an isomorphism in the record component -bijection. -

-For the same reason as in , -&GAP; 4 puts emphasis on the isomorphism, -and the isomorphic object in the desired representation can be accessed -as its image. -So you can call IsomorphismPcGroup or IsomorphismPermGroup in order -to get an isomorphism to a polycyclically presented group or a -permutation group, respectively, and then call Image to get the -isomorphic group. -

-Note that the image of an action homomorphism with trivial kernel is -also an isomorphic permutation group, but an action homomorphism need -not be surjective, since it may be easier to define it into the full -symmetric group. -

-Further note that in &GAP; 3, a usual application of isomorphisms to -polycyclically presented groups was to utilize the usually more -effective algorithms for solvable groups. However, the new concept of -polycyclic generating systems in &GAP; 4 makes it possible to apply -these algorithms to arbitrary solvable groups, independent of the -representation. For example, &GAP; 4 can handle polycyclic -generating systems of solvable permutation groups. So in many cases, -a change of the representation for efficiency reasons may be not -necessary any longer. -

-In general IsomorphismFpGroup will define a presentation on generators -chosen by the algorithm. The corresponding elements of the original -group can be obtained by the command -

-PreImagesRepresentative(isofp,i)); -]]> -

-If a presentation in the given generators is needed, the command -IsomorphismFpGroupByGenerators(G, gens) will produce one. - -

- - - -
-Elements of Finitely Presented Groups - -Strictly speaking, &GAP; 3 did not support elements of finitely -presented groups. Instead, the words in abstract generators of -the underlying free groups were (mis)used. This caused problems -whenever calculations with elements were involved, the most obvious -ones being wrong results of element comparisons. Also functions -that should in principle work for any group were not applicable to -finitely presented groups. In effect, a finitely presented group had -to be treated in a special way in &GAP; 3. -

-&GAP; 4 distinguishes free groups and their elements from finitely -presented groups and their elements. Comparing two elements of a -finitely presented group will yield either the correct result or no -result at all. -

-Note that in &GAP; 4, the arithmetic and comparison operations for -group elements do not depend on a context provided by a group that -contains the elements. In particular, in &GAP; 4 it is not -meaningful to call Order( G, g ) for a group G and an element -g. - -

- - - -
-Polynomials - -In &GAP; 3, polynomials were defined over a field. So a polynomial over -GF(3) was different from a polynomial over GF(9), even if the -coefficients were exactly the same. -

-&GAP; 4 defines polynomials only over a characteristic. This makes it -possible for example to multiply a polynomial over GF(3) with a polynomial -over GF(9) without the need to convert the former to the larger field. -

-However it has an effect on the result of DefaultRing for polynomials: -In &GAP; 3 the default ring for a polynomial was the polynomial ring of the -field over which the polynomial was defined. In &GAP; 4 no field is -associated, so (to avoid having to define the algebraic closure as the only -other sensible alternative) the default ring of a polynomial is the -DefaultRing of its coefficients. -

-This has an effect on Factors: If no ring is given, a polynomial is -factorized over its DefaultRing and so Factors(poly) -might return different results. -

-To be safe from this problem, if you are not working over prime fields, -rather call Factors(pring,poly) with the appropriate polynomial ring -and change your code accordingly. - -

- - - -
-The Info Mechanism - -Sometimes it is useful to get information about the progress of a -calculation. -Many &GAP; functions contain statements to display such information -under certain conditions. -

-In &GAP; 3, these statements were calls to functions such as -InfoGroup1 or InfoGroup2, and if the user assigned Print to -these variables then this had the effect to switch on the printing of -information. -InfoGroup2 was used for more detailed information than InfoGroup1. -One could switch off the printing again by assigning Ignore to the -variables, and Ignore was also the default value. -

-&GAP; 4 uses one function Info for the same purpose, -which is a function that takes as first argument an info class such as -InfoGroup, as second argument an info level, and the print statements -as remaining arguments. -The level of an info class class is set to level by calling -SetInfoLevel( class, level ). -An Info statement is printed only if its second argument is smaller than -or equal to the current info level. -

- test:= function( obj ) -> Info( InfoGroup, 2, "This is useful, isn't it?" ); -> return obj; -> end;; -gap> test( 1 ); -1 -gap> SetInfoLevel( InfoGroup, 2 ); -gap> test( 1 ); -#I This is useful, isn't it? -1 -]]> -

-As in &GAP; 3, if an info statement is ignored then its arguments are -not evaluated. - -

- - - -
-Debugging - -Backtrace -DownEnv -Where -If &GAP; 4 runs into an error or is interrupted, -it enters a break loop. -The command Where( number ), which replaces Backtrace of &GAP; 3, -can be used to display number lines of information about the current -function call stack. -

-As in &GAP; 3, access is only possible to the variables of the current -level in the function stack, -but in &GAP; 4 the function DownEnv, with a positive or negative -integer as argument, permits one to step down or up in the -stack. -

-When interrupting, the first line printed by Where actually may be -one level higher, as shown below. -

- OnBreak := function() end;; # eliminate back-tracing on entry to break loop -gap> test:= function( n ) -> if n > 3 then Error( "!\n" ); fi; test( n+1 ); end;; -gap> test( 1 ); -Error, ! -you can enter 'quit;' to quit to outer loop, or -you can enter 'return;' to continue -brk> Where(); -Stack trace: -*[1] Error( "!\n" ); - @ *stdin*:3 - [2] test( n + 1 ); - @ *stdin*:3 - [3] test( n + 1 ); - @ *stdin*:3 - [4] test( n + 1 ); - @ *stdin*:3 -( ) - called from read-eval loop at *errin*:1 -brk> n; -4 -brk> DownEnv(); -brk> n; -3 -brk> Where(); -Stack trace: - [1] Error( "!\n" ); - @ *stdin*:3 -*[2] test( n + 1 ); - @ *stdin*:3 - [3] test( n + 1 ); - @ *stdin*:3 - [4] test( n + 1 ); - @ *stdin*:3 -( ) - called from read-eval loop at *errin*:5 -brk> DownEnv( 2 ); -brk> n; -1 -brk> Where(); -Stack trace: - [1] Error( "!\n" ); - @ *stdin*:3 - [2] test( n + 1 ); - @ *stdin*:3 - [3] test( n + 1 ); - @ *stdin*:3 -*[4] test( n + 1 ); - @ *stdin*:3 -( ) - called from read-eval loop at *errin*:8 -brk> DownEnv( -2 ); -brk> n; -3 -brk> quit; -gap> OnBreak := Where;; # restore OnBreak to its default value -]]> -

-For purposes of debugging, it can be helpful sometimes, to see what -information is stored within an object. In &GAP; 3 this was possible using -RecFields because the objects in question were represented via records. -For component objects, &GAP; 4 permits the same by -NamesOfComponents( object ), which will list all components present. - -

- - - -
-Compatibility Mode - -For users who want to use &GAP; 3 code with as little changes as -possible, a compatibility mode is provided by &GAP; 4. -This mode must be turned on explicitly by the user. -

-It should be noted that this compatibility mode has not been tested -thoroughly. -

-The compatibility mode can be turned on by loading some of the following -files with ReadLib. -The different files address different aspects of compatibility. -

- -compat3a.g - - makes some &GAP; 3 function names available that were changed - in &GAP; 4, - and provides code for some &GAP; 3 features that were - deliberately left out from the &GAP; 4 library. - For example, - almost all variable names concerning character theory that are - mentioned in the &GAP; 3 manual, - such as CharTable and SubgroupFusions, - are available after compat3a.g has been read; - the only exceptions are names of operations records. - -compat3b.g - - implements the availability of components of domains; - besides components that have no meaning for the rest of the &GAP; 4 - library, such as D.myInfo, there are components associated to - attributes; for example D.size is redirected to the call of the - attribute Size, IsBound( D.size ) to the call of its tester, - and D.size:= val to the call of its setter. - (An important special case is the component operations, see below.) - -compat3c.g - - permits you to implement your own elements represented as records, - and using operations records to provide a Print method and - the basic arithmetic operations. - When using operations records, it is probably a good idea to - use immutable operations records; for example, if the results - of arithmetic operations are records with operations records then - this avoids to create shallow copies of the operations records - in the call to Immutable for the results. - - -

-The following features are accessible only via starting &GAP; with -the command line option -O and may damage some features of &GAP; 4 -permanently for the current session. -

- With this option, also the files listed above are read automatically. -

- -compat3d.g - - provides some &GAP; 3 functions like Domain, simulates the - &GAP; 3 behaviour of IsString (to convert a list to string - representation if possible), and replaces fail by false; - these changes destroy parts of the functionality of &GAP; 4. - - -

-Some words concerning the simulation of operations records may be -necessary. -

-The operations records of the &GAP; 3 library, such as DomainOps -and GroupOps, are available only for access to their components, -whose values are &GAP; 4 operations; for example, the value of both -DomainOps.Size and GroupOps.Size is the operation Size. So it -is not safely possible to delegate from a Size method in another -operations record to DomainOps.Size. Also it is not possible to -change these predefined operations records. -

-If one wants to install individual methods for a given object obj -via the mechanism of operations records then one can construct a new -operations record with OperationsRecord, assign the desired methods -to components of this record, and then assign the operations record to -obj.operations. Whenever an operation that is associated with a -component nam of the operations record is called with obj as first -argument, the value of nam is chosen as the method. -

-In the case of the binary operations =, <, +, -, *, /, -Comm, and LeftQuotient, -this also happens if obj is the right-hand argument. -As in &GAP; 3, if both arguments of one of the above binary operations -have operations records containing a function for this operation, -then the function in the operations record of the right-hand argument -is chosen. -

-We give a small example how the compatibility mode works. -

-Suppose we want to deal with new objects that are derived from known -field elements by distorting their multiplication. Namely, let a' -and b' be the new objects corresponding to the field elements a, -b, and define a' * b' = a b - a - b + 2. -

-In &GAP; 3, this problem was solved by representing each new object -by a record that stored the corresponding old object and an -operations record, where the latter was a record containing the -functions applicable to the new object. After the library file -compat3c.g has been read, we can use this construction of the -operations record and of the new objects. Note that operations -records must be created with the function OperationsRecord (this was -also the norm in &GAP; 3), starting with an empty record would not work. -For our intended application, we thus start with the following two -lines of code. -

- ReadLib( "compat3c.g" ); -gap> MyOps:= OperationsRecord( "MyOps" );; -HasMyOps := NewFilter( "HasMyOps" ); -]]> -

-In order to make the translation from &GAP; 3 code to &GAP; 4 -easier, &GAP; prints the definition of filters associated with -operations records and the method installations for operations -corresponding to components of the operations records. The output -line printed by &GAP; after the call of OperationsRecord is one -such case. -

-Now we add our multiplication function to the operations record, -and again &GAP; 4 prints a translation to &GAP; 4 code. -

- MyOps.\* := function( a, b ) -> return rec( x:= a.x * b.x - a.x - b.x + 2, -> operations := MyOps ); -> end;; -# If the following method installation matches the requirements -# of the operation `PROD' then `InstallMethod' should be used. -# It might be useful to replace the rank `SUM_FLAGS' by `0'. -InstallOtherMethod( PROD, - "for object with `MyOps' as first argument", - true, - [ HasMyOps, IsObject ], SUM_FLAGS, - MyOps.\* ); - -# For binary infix operators, a second method is installed -# for the case that the object with `MyOps' is the right operand; -# since this case has higher priority in GAP 3, the method is -# installed with higher rank `SUM_FLAGS + 1'. -InstallOtherMethod( PROD, - "for object with `MyOps' as second argument", - true, - [ IsObject, HasMyOps ], SUM_FLAGS + 1, - MyOps.\* ); -]]> -

-Let us look how this installation works. -

- a:= rec( x:= 3, operations:= MyOps ); -rec( x := 3, operations := MyOps ) -gap> b:= rec( x:= 5, operations:= MyOps ); -rec( x := 5, operations := MyOps ) -gap> a * b; -rec( x := 9, operations := MyOps ) -]]> -

-(In more complicated cases, we might run into problems, but this was -already the case in &GAP; 3. For example, suppose we want to support -the multiplication of two operands having different operations -records; then it is not clear which of the two multiplication -functions is to be chosen, and in &GAP; 3, the only way out was to -change the multiplication functions, in order to make them aware of -such situations.) -

-If we are now interested to translate the code to &GAP; 4 in the -sense that no compatibility mode is needed, we can use what &GAP; 4 -has printed above. (The same example is dealt with in -Chapter .) -

-The objects will no longer be records with operations component. -Instead of records we may use so-called component objects -with record-like access to components, -and instead of the operations component, we give the objects a -type that has the filter HasMyOps set. -

- -

-(More about families and representations in this context can be found -in the chapter of Programming in &GAP; mentioned above.) -

-The next step is to write a function that creates a new object. -It may look as follows. -

- -

-The multiplication function shall return an object with the -filter HasMyOp, so we change it as follows. -

- MyMult := function( a, b ) -> return MyObject( x:= a!.x * b!.x - a!.x - b!.x + 2 ); -> end;; -]]> -

-Note that the component access for these objects -works via !. instead of .; -further note that no operations record needs to appear here, -the filter takes its role. -

-Finally, we install the multiplication for at least one argument -with the new filter, as had been printed by &GAP; 4 in the -session shown above. -

- -

-And now it works (again). -

- a:= MyObject( 3 ); - -gap> b:= MyObject( 5 ); - -gap> a * b; - -gap> last!.x -9 -]]> -

-We may install a method to print our objects in a nice way; -we could have done this for the operations record MyOps -in the compatibility mode, -the printed output would look similar to the following. -

- -

-Now output looks as follows. -

- a; b; a * b; -MyObject( 3 ) -MyObject( 5 ) -MyObject( 9 ) -]]> -

-Maybe now we want to improve the installation. -The multiplication function we want to use is apparently -thought only for the case that both operands have -the filter HasMyOps (and a component x). -So it is reasonable to replace the two methods for -the multiplication by one method for which both arguments -are required to have the filter. -

- -

-At first sight, the &GAP; 4 approach seems to be much more -complicated. -But the last example shows that in &GAP; 4, -each method can be installed more specifically for the appropriate -situation. -Moreover, it is for example possible to install a method -for the multiplication of an integer and a HasMyOps object; -note that --contrary to the situation in &GAP; 3-- -such a method is independent from already existing methods -in the sense that these need not be changed when -new functionality is added. -

-Another example that uses this part of the compatibility mode can be -found in the file tst/compat3.tst of the &GAP; 4 distribution. - - - - - - - - From f7afbcccb548cba489df99b474d7d7627f41df13 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 11 Jun 2026 09:16:17 +0200 Subject: [PATCH 038/114] Remove SingleCollector_CollectWordRunning (#6426) It does not seem to serve any purpose (anymore?) --- lib/rwspcsng.gi | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/rwspcsng.gi b/lib/rwspcsng.gi index 19cd81bcec..81bfcdb7a3 100644 --- a/lib/rwspcsng.gi +++ b/lib/rwspcsng.gi @@ -71,8 +71,6 @@ DeclareFilter( "IsDefaultRhsTypeSingleCollector" ); ## describing the polycyclic presentation, an exponent vector and a word ## in the corresponding free group. It collects into . ## -SingleCollector_CollectWordRunning := false; - BindGlobal( "SingleCollector_CollectWord", function( sc, v, w ) local cnj, # [g][h] contains g^h for g > h @@ -92,13 +90,7 @@ BindGlobal( "SingleCollector_CollectWord", function( sc, v, w ) tmp, # temporary avc; # g_i .. g_n commutes with g_avc[i]+1 .. g_n - # the collector is not reentrant - if SingleCollector_CollectWordRunning then - SingleCollector_CollectWordRunning := false; - Error( "collector is not reentrant" ); - fi; #Print( "#I using the GAP level single collector\n" ); - SingleCollector_CollectWordRunning := true; # contains the stack of words to insert nw := []; nw[1] := w; @@ -108,7 +100,6 @@ BindGlobal( "SingleCollector_CollectWord", function( sc, v, w ) # if we got the identity return if lw[1] = 0 then - SingleCollector_CollectWordRunning := false; return true; fi; @@ -238,7 +229,6 @@ BindGlobal( "SingleCollector_CollectWord", function( sc, v, w ) fi; fi; od; - SingleCollector_CollectWordRunning := false; return true; end ); From 4fea97426ec77cca945959cda2ccff2e043b4295 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 11 Jun 2026 13:29:42 +0200 Subject: [PATCH 039/114] kernel: cleanup CRC code (#6436) There was an incorrect comment claiming that SyGAPCRC only ever returns 0 in case of an error. There was also code that looked as if it ensured that (by checking if `crc` is 0 and if so replacing it by 1). But this code in fact was a no-op, and has been one since 1997, when the code was changed to return `crc >> 4` instead of `crc` -- yet both `0 >> 4` and `1 >> 4` are equal to 0. Regarding the other changes: - `(crc >> 8) & 0x00FFFFFFL` is the same as `crc >> 8` since `crc` is an unsigned 32 bit value - removed a comment from the 1990ies suggesting that `SyGAPCRC` should ignore whitespace and comment changes; but we will never do that (as it would be very difficult, break backwards compatibility, and have little practical use) - align right shift in SyGAPCRC and FuncCrcString: one was "emulating" a signed shift, the other didn't. This didn't cause a problem in practice because essentially every compiler in active uses nowadays implements signed right shifts; but the C standard does not require this. Now both use the same branchless emulation code which e.g. clang compiles down into a single instruction (GCC, MSVC, ICC do not, but that's fine, this code is not a bottleneck for anything) --- src/gap.c | 4 +--- src/sysfiles.c | 41 ++++++++++++++++++----------------------- src/sysfiles.h | 3 +-- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/gap.c b/src/gap.c index 711c0eb142..e88bcc8711 100644 --- a/src/gap.c +++ b/src/gap.c @@ -409,7 +409,6 @@ int realmain(int argc, const char * argv[]) { UInt type; // result of compile Obj func; // function (compiler) - Int4 crc; // crc of file to compile // initialize everything and read init.g which runs the GAP session InitializeGap(&argc, argc, argv, 1); @@ -425,12 +424,11 @@ int realmain(int argc, const char * argv[]) if (!CloseInput(&input)) { return 2; } - crc = SyGAPCRC(SyCompileInput); type = CompileFunc( MakeImmString(SyCompileOutput), func, MakeImmString(SyCompileName), - crc, + SyGAPCRC(SyCompileInput), MakeImmString(SyCompileMagic1) ); return ( type == 0 ) ? 1 : 0; } diff --git a/src/sysfiles.c b/src/sysfiles.c index b65033dbe1..98aeb14694 100644 --- a/src/sysfiles.c +++ b/src/sysfiles.c @@ -191,10 +191,7 @@ static ssize_t echoandcheck(int fid, const char *buf, size_t count) ** *F SyGAPCRC( ) . . . . . . . . . . . . . . . . . . crc of a GAP file ** -** This function should be clever and handle white spaces and comments but -** one has to make certain that such characters are not ignored in strings. -** -** This function *never* returns a 0 unless an error occurred. +** This function returns 0 for missing or unreadable files. */ static const UInt4 syCcitt32[ 256 ] = { @@ -248,7 +245,7 @@ Int4 SyGAPCRC( const Char * name ) UInt4 crc; UInt4 old; UInt4 new; - Int4 ch; + Int ch; Int fid; BOOL seen_nl; @@ -273,21 +270,18 @@ Int4 SyGAPCRC( const Char * name ) } else seen_nl = FALSE; - old = (crc >> 8) & 0x00FFFFFFL; - new = syCcitt32[ ( (UInt4)( crc ^ ch ) ) & 0xff ]; + old = crc >> 8; + new = syCcitt32[(crc ^ ch) & 0xff]; crc = old ^ new; } - if ( crc == 0 ) { - crc = 1; - } // and close it again SyFclose( fid ); - // Emulate a signed shift: - if (crc & 0x80000000L) - return (Int4) ((crc >> 4) | 0xF0000000L); - else - return (Int4) (crc >> 4); + + // Emulate a signed shift (the C compiler does not specify whether right + // shifts preserve signs or not; it seems more or less all compilers in + // active use these days do, but better safe than sorry) + return ((Int)((crc >> 4) ^ 0x08000000U)) - 0x08000000; } @@ -320,7 +314,7 @@ static Obj FuncCrcString(Obj self, Obj str) UInt4 new; UInt4 i, len; const Char *ptr; - Int4 ch; + Int ch; BOOL seen_nl; RequireStringRep(SELF_NAME, str); @@ -330,7 +324,7 @@ static Obj FuncCrcString(Obj self, Obj str) crc = 0x12345678L; seen_nl = FALSE; for (i = 0; i < len; i++) { - ch = (Int4)(ptr[i]); + ch = (Int)(ptr[i]); if ( ch == '\377' || ch == '\n' || ch == '\r' ) ch = '\n'; if ( ch == '\n' ) { @@ -341,14 +335,15 @@ static Obj FuncCrcString(Obj self, Obj str) } else seen_nl = FALSE; - old = (crc >> 8) & 0x00FFFFFFL; - new = syCcitt32[ ( (UInt4)( crc ^ ch ) ) & 0xff ]; + old = crc >> 8; + new = syCcitt32[(crc ^ ch) & 0xff]; crc = old ^ new; } - if ( crc == 0 ) { - crc = 1; - } - return INTOBJ_INT(((Int4) crc) >> 4); + + // Emulate a signed shift (the C compiler does not specify whether right + // shifts preserve signs or not; it seems more or less all compilers in + // active use these days do, but better safe than sorry) + return INTOBJ_INT(((Int)((crc >> 4) ^ 0x08000000U)) - 0x08000000); } // Get OS Kernel version. Used to discover if GAP is running inside diff --git a/src/sysfiles.h b/src/sysfiles.h index 046ea30b68..96799788ee 100644 --- a/src/sysfiles.h +++ b/src/sysfiles.h @@ -23,8 +23,7 @@ ** *F SyGAPCRC( ) . . . . . . . . . . . . . . . . . . crc of a GAP file ** -** This function should be clever and handle white spaces and comments but -** one has to certain that such characters are not ignored in strings. +** This function returns 0 for missing or unreadable files. */ Int4 SyGAPCRC(const Char * name); From 3cd543fffe76a210f349a657d34347cd9038cec1 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 11 Jun 2026 22:40:12 +0200 Subject: [PATCH 040/114] doc: fix typo (#6438) --- doc/ref/helpintf.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ref/helpintf.xml b/doc/ref/helpintf.xml index 6ed9b9be27..3daccf2773 100644 --- a/doc/ref/helpintf.xml +++ b/doc/ref/helpintf.xml @@ -164,7 +164,7 @@ gap> stream := InputTextFile( file );; This must return a text string or list of text lines which contains the chapter headers of the book info.bookname. -ShowSection( info ) +ShowSections( info ) This must return a text string or list of text lines which contains the section (and chapter) headers of the book info.bookname. From f49b3f874aeb638feded172754491369e942e0e7 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 18 Jun 2026 15:52:03 +0100 Subject: [PATCH 041/114] replaced 'return []' by 'return fail' --- lib/field.gi | 4 ++-- lib/fldabnum.gi | 4 ++-- lib/ghomfp.gi | 2 +- lib/liefam.gi | 2 +- lib/mapping.gi | 8 ++++---- lib/relation.gi | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/field.gi b/lib/field.gi index ff2e31c3ba..6223cf0535 100644 --- a/lib/field.gi +++ b/lib/field.gi @@ -1338,7 +1338,7 @@ InstallMethod( PreImagesElm, [ IsFieldHomomorphism, IsObject ], function ( hom, elm ) if not (elm in Range(hom)) then - return []; + return fail; fi; return PreImagesElm( hom, elm ); end ); @@ -1365,7 +1365,7 @@ InstallMethod( PreImagesSet, [ IsFieldHomomorphism, IsField ], function ( hom, elms ) if not IsSubset( Range(hom), elms ) then - return []; + return fail; fi; return PreImagesSet( hom, elms ); end ); diff --git a/lib/fldabnum.gi b/lib/fldabnum.gi index 6c5f22d030..cfc60cc6d9 100644 --- a/lib/fldabnum.gi +++ b/lib/fldabnum.gi @@ -1936,7 +1936,7 @@ InstallMethod( PreImagesElm, [ IsFieldHomomorphism and IsANFAutomorphismRep, IsScalar ], function ( aut, elm ) if not ( elm in Range(aut) ) then - return []; + return fail; fi; return PreImagesElmNC( aut, elm ); end ); @@ -1960,7 +1960,7 @@ InstallMethod( PreImagesSet, [ IsFieldHomomorphism and IsANFAutomorphismRep, IsField ], function ( aut, F ) if not IsSubset( Range(aut), F ) then - return []; + return fail; fi; return PreImagesSetNC( aut, F ); end ); diff --git a/lib/ghomfp.gi b/lib/ghomfp.gi index fc045d8289..86d7fa5a9f 100644 --- a/lib/ghomfp.gi +++ b/lib/ghomfp.gi @@ -630,7 +630,7 @@ InstallMethod( PreImagesSet, "map from (sub)group of fp group", [ IsFromFpGroupHomomorphism,IsGroup ],0, function(hom,u) if not IsSubset( Range(hom), u ) then - return []; + return fail; fi; return PreImagesSetNC(hom,u); end); diff --git a/lib/liefam.gi b/lib/liefam.gi index 0a5590b03d..0f9f70c53f 100644 --- a/lib/liefam.gi +++ b/lib/liefam.gi @@ -463,7 +463,7 @@ InstallMethod( PreImagesElm, IsLieObject and IsPackedElementDefaultRep ], 0, function( emb, elm ) if not ( elm in Range(emb) ) then - return []; + return fail; fi; return PreImagesElm( emb, elm ); end ); diff --git a/lib/mapping.gi b/lib/mapping.gi index f54e58ee2d..5069534ba6 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -1159,7 +1159,7 @@ InstallMethod( PreImagesElm, function ( map, elm ) if not ( elm in Image( map ) ) then - return []; + return fail; else return PreImagesElmNC( map, elm ); fi; @@ -1192,7 +1192,7 @@ InstallMethod( PreImagesElm, [ IsGeneralMapping and IsConstantTimeAccessGeneralMapping, IsObject ], 0, function( map, elm ) if not ( elm in Image( map ) ) then - return []; + return fail; else return PreImagesElmNC( map, elm ); fi; @@ -1233,7 +1233,7 @@ InstallMethod( PreImagesSet, im:= Image( map ); for elm in Enumerator( elms ) do if not (elm in im ) then - return []; + return fail; fi; od; return PreImagesSetNC( map, elms ); @@ -1331,7 +1331,7 @@ InstallMethod( PreImagesRepresentative, [ IsNonSPGeneralMapping, IsObject ], 0, function( map, elm ) if not elm in Image( map ) then - return []; + return fail; fi; return PreImagesRepresentativeNC( map, elm ); end ); diff --git a/lib/relation.gi b/lib/relation.gi index e349d50d5e..db6005a732 100644 --- a/lib/relation.gi +++ b/lib/relation.gi @@ -1001,7 +1001,7 @@ InstallMethod(PreImagesElm, true, [IsBinaryRelation and IsBinaryRelationOnPointsRep, IsPosInt], 0, function( rel, n ) if not ( n in Range(rel) ) then - return []; + return fail; fi; return PreImagesElm( rel, n ); end ); @@ -1855,7 +1855,7 @@ InstallMethod( PreImagesElm, IsObject],0, function( rel, elm ) if not ( elm in Range( rel ) ) then ##?? is there a Range(rel)? - return []; + return fail; fi; return PreImagesElmNC( rel, elm ); end); From f3dd6175d94c2aa25cfa74ed01f13487943f1503 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jun 2026 10:20:59 +0200 Subject: [PATCH 042/114] build(deps): bump actions/checkout from 6 to 7 (#6444) Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/CI.yml | 6 +++--- .github/workflows/gapjl.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/release.yml | 6 +++--- .github/workflows/update-gh-pages.yml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index e9937fed7f..e2586f8e27 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -141,7 +141,7 @@ jobs: TEST_SUITES: ${{ matrix.test-suites }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: "Set up Python" uses: actions/setup-python@v6 @@ -341,7 +341,7 @@ jobs: - name: Install cross compile dependencies run: sudo apt-get install -q -y libgmp-dev:s390x libreadline-dev:s390x zlib1g-dev:s390x - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - run: ./autogen.sh @@ -407,7 +407,7 @@ jobs: env: AUTOCONF_VERSION: 2.71 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Download required GAP packages run: | diff --git a/.github/workflows/gapjl.yml b/.github/workflows/gapjl.yml index 626f1a52a1..54032f9ed4 100644 --- a/.github/workflows/gapjl.yml +++ b/.github/workflows/gapjl.yml @@ -44,7 +44,7 @@ jobs: steps: - name: Checkout GAP - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: path: 'GAPROOT' - name: "Set up Julia" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index bbf8e68ac8..63eca8aeb6 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-slim steps: - name: "Check out the repository" - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: "Set up Python" uses: actions/setup-python@v6 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index eb4ce3c91b..8c2b84a1ba 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,7 @@ jobs: name: "Validate release scripts" runs-on: ubuntu-slim steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: "Set up Python" uses: actions/setup-python@v6 @@ -72,7 +72,7 @@ jobs: # requires fetching the entire history. Therefore, we might as well do # that here when checking out the repo, which is what setting fetch-depth # to 0 accomplishes here. - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 @@ -207,7 +207,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: "Clone the Windows installer maker scripts" - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: gap-system/gap-windows ref: main diff --git a/.github/workflows/update-gh-pages.yml b/.github/workflows/update-gh-pages.yml index e1ebb2c57b..cbafbb0093 100644 --- a/.github/workflows/update-gh-pages.yml +++ b/.github/workflows/update-gh-pages.yml @@ -41,7 +41,7 @@ jobs: sudo apt-get update sudo apt-get install --no-install-recommends "${packages[@]}" - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Configure GAP run: | ./autogen.sh && ./configure From 853273799e003388376948131fb60a86c06855ed Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 23 Jun 2026 11:10:59 +0200 Subject: [PATCH 043/114] Remove InfoData, make INFO_CLASSES readonly (#6443) --- lib/info.gi | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/info.gi b/lib/info.gi index 7436dfa86b..7c873f9661 100644 --- a/lib/info.gi +++ b/lib/info.gi @@ -45,11 +45,7 @@ DeclareRepresentation("IsInfoClassListRep", IsAtomicPositionalObjectRep); # A list of all created InfoClassListReps -INFO_CLASSES := []; - -# InfoData is unused, but we keep it for now, to avoid warnings in GAPDoc. -# TODO: remove InfoData -InfoData := rec(); +BIND_GLOBAL( "INFO_CLASSES", [] ); if IsHPCGAP then ShareInternalObj(INFO_CLASSES); From 16256d19fc45b83d55bb8174b57185364a5cbdbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Wed, 24 Jun 2026 15:32:06 +0200 Subject: [PATCH 044/114] Move over changes to the GAP.jl-CI job (#6445) Also treat readline headers as system includes. This avoids Homebrew readline header warnings under --enable-Werror. Co-authored-by: Max Horn Co-authored-by: Codex --- .github/workflows/gapjl.yml | 22 +++++++++++++++++++++- configure.ac | 4 ++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gapjl.yml b/.github/workflows/gapjl.yml index 54032f9ed4..f23b79ddab 100644 --- a/.github/workflows/gapjl.yml +++ b/.github/workflows/gapjl.yml @@ -67,11 +67,31 @@ jobs: - name: "Install dependencies (for macOS)" if: runner.os == 'macOS' run: | - brew install autoconf zlib # gmp pkg-config + # - autoconf, gmp, zlib are needed by GAP's build system + # - coreutils provides nproc + # - force use of Homebrew gcc to build GAP for proper stacktrace support + # Homebrew installs versioned binaries such as gcc-14 and g++-14, + # while later scripts expect unversioned gcc and g++ in PATH. + brew install autoconf gmp zlib gcc@14 coreutils + + # ensure gcc and g++ are available under those names (on macOS, + # these names are aliases for clang / clang++ out of the box) + shimdir="${HOME}/bin" + mkdir -p "${shimdir}" + ln -sf "$(brew --prefix)/bin/gcc-14" "${shimdir}/gcc" + ln -sf "$(brew --prefix)/bin/g++-14" "${shimdir}/g++" + echo "${shimdir}" >> "${GITHUB_PATH}" - name: "Build GAP" run: | mv GAPROOT /tmp/GAPROOT cd /tmp/GAPROOT + patchdir=$GAPJLPATH/.github/workflows/GAP_patches/master + if [ -d $patchdir ]; then + for f in $patchdir/*.patch; do + echo "Applying patch ${f}" + patch -p1 -d . < ${f} + done + fi ./autogen.sh ./configure --enable-Werror make -j`nproc` diff --git a/configure.ac b/configure.ac index 9320f18ce0..10b9b528f8 100644 --- a/configure.ac +++ b/configure.ac @@ -727,12 +727,12 @@ for READLINE_PREFIX in ${READLINE_SEARCH_PATH} ; do [DEFAULTS_EREADLINE],[ dnl ereadline is the name of GNU readline library on OpenBSD READLINE_PREFIX="" - READLINE_CPPFLAGS="-I/usr/local/include/ereadline" + READLINE_CPPFLAGS="-isystem /usr/local/include/ereadline" READLINE_LDFLAGS="" READLINE_LIBS="-lereadline" ], [*],[ - READLINE_CPPFLAGS="-I${READLINE_PREFIX}/include" + READLINE_CPPFLAGS="-isystem ${READLINE_PREFIX}/include" READLINE_LDFLAGS="-L${READLINE_PREFIX}/lib" READLINE_LIBS="-lreadline" ] From bd1a466de433d24532640f16dfda6a33e230a7a8 Mon Sep 17 00:00:00 2001 From: Alexander Hulpke Date: Wed, 1 Jul 2026 05:15:02 -0600 Subject: [PATCH 045/114] Perfect groups data is licensed under GPL 2.0 or later (#6450) --- grp/perf13.grp | 2 +- grp/perf14.grp | 2 +- grp/perf15.grp | 2 +- grp/perf16.grp | 2 +- grp/perf17.grp | 2 +- grp/perf18.grp | 2 +- grp/perf19.grp | 2 +- grp/perf20.grp | 2 +- grp/perf21.grp | 2 +- grp/perf22.grp | 2 +- grp/perf23.grp | 2 +- grp/perf24.grp | 2 +- grp/perf25.grp | 2 +- grp/perf26.grp | 2 +- grp/perf28.grp | 2 +- grp/perf29.grp | 2 +- grp/perf30.grp | 2 +- grp/perf31.grp | 2 +- grp/perf32.grp | 2 +- grp/perf34.grp | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/grp/perf13.grp b/grp/perf13.grp index 0f9a715bf9..9a66aacec6 100644 --- a/grp/perf13.grp +++ b/grp/perf13.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[96]:=[# 61440.1 [[1,"abcde", diff --git a/grp/perf14.grp b/grp/perf14.grp index eccd748827..fe20d8d587 100644 --- a/grp/perf14.grp +++ b/grp/perf14.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[111]:=[# 86016.1 [[1,"abcd", diff --git a/grp/perf15.grp b/grp/perf15.grp index 3e466c5c5b..96880d1a09 100644 --- a/grp/perf15.grp +++ b/grp/perf15.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[131]:=[# 122880.1 [[1,"abcdef", diff --git a/grp/perf16.grp b/grp/perf16.grp index 31da9f936f..3d74dd9c6e 100644 --- a/grp/perf16.grp +++ b/grp/perf16.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[150]:=[# 172032.1 [[1,"abc", diff --git a/grp/perf17.grp b/grp/perf17.grp index dce726788d..9f569b8930 100644 --- a/grp/perf17.grp +++ b/grp/perf17.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[179]:=[# 245760.1 [[1,"abcde", diff --git a/grp/perf18.grp b/grp/perf18.grp index e142e995b2..66d6548ebd 100644 --- a/grp/perf18.grp +++ b/grp/perf18.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[200]:=[# 344064.1 [[1,"abcd", diff --git a/grp/perf19.grp b/grp/perf19.grp index abcc2320e7..cbe80ff733 100644 --- a/grp/perf19.grp +++ b/grp/perf19.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[210]:=[# 368640.1 [[1,"abcdef", diff --git a/grp/perf20.grp b/grp/perf20.grp index d9fec32164..d14b2567e8 100644 --- a/grp/perf20.grp +++ b/grp/perf20.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[244]:=[# 491520.1 [[1,"abcde", diff --git a/grp/perf21.grp b/grp/perf21.grp index 5488fdc506..0a723692a3 100644 --- a/grp/perf21.grp +++ b/grp/perf21.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[276]:=[# 688128.1 [[1,"abcde", diff --git a/grp/perf22.grp b/grp/perf22.grp index ab14628e3f..873de9394a 100644 --- a/grp/perf22.grp +++ b/grp/perf22.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later number:=[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 7, 1, 1, 1, 1, 3, 1, 1, 1, 7, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 5, 1, 1, 3, 1, 1, 9, 4, 1, 1, diff --git a/grp/perf23.grp b/grp/perf23.grp index b260d3a331..e7cc9f0523 100644 --- a/grp/perf23.grp +++ b/grp/perf23.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[330]:=[# 983040.1 [[1,"abcdef", diff --git a/grp/perf24.grp b/grp/perf24.grp index 672b2f4d84..b48d5514f9 100644 --- a/grp/perf24.grp +++ b/grp/perf24.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[332]:=[# 1008000.1 [[1,"abcdef", diff --git a/grp/perf25.grp b/grp/perf25.grp index 1e51e86fc2..a3967e1db6 100644 --- a/grp/perf25.grp +++ b/grp/perf25.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[355]:=[# 1180980.1 [[1,"abcde", diff --git a/grp/perf26.grp b/grp/perf26.grp index f7486d8e91..7af1e2a545 100644 --- a/grp/perf26.grp +++ b/grp/perf26.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[371]:=[# 1290240.1 [[1,"abcdefg", diff --git a/grp/perf28.grp b/grp/perf28.grp index 69b0382d26..c9f45efb72 100644 --- a/grp/perf28.grp +++ b/grp/perf28.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[382]:=[# 1382400.1 [[1,"abcdefg", diff --git a/grp/perf29.grp b/grp/perf29.grp index fcffbacfd0..dcdc30b9e0 100644 --- a/grp/perf29.grp +++ b/grp/perf29.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[396]:=[# 1474560.1 [[1,"abcdefg", diff --git a/grp/perf30.grp b/grp/perf30.grp index 09144844f8..948a0c1e02 100644 --- a/grp/perf30.grp +++ b/grp/perf30.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[421]:=[# 1749600.1 [[1,"abcdefgh", diff --git a/grp/perf31.grp b/grp/perf31.grp index ca3418d68a..afc2d69797 100644 --- a/grp/perf31.grp +++ b/grp/perf31.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[435]:=[# 1843200.1 [[1,"abcdef", diff --git a/grp/perf32.grp b/grp/perf32.grp index a33d812d03..ee0f128a89 100644 --- a/grp/perf32.grp +++ b/grp/perf32.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[436]:=[# 1843968.1 [[1,"abcdef", diff --git a/grp/perf34.grp b/grp/perf34.grp index e78fe08416..683173f859 100644 --- a/grp/perf34.grp +++ b/grp/perf34.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[452]:=[# 1975680.1 [[1,"abcd", From 29814efe44c3a1dfd5d9e7a2b784586a081adcc4 Mon Sep 17 00:00:00 2001 From: Thomas Breuer Date: Wed, 1 Jul 2026 13:17:18 +0200 Subject: [PATCH 046/114] Add an argument check to `CodePcgs` (#6451) --- lib/randiso.gi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/randiso.gi b/lib/randiso.gi index 5331eb51c3..15b1d8c520 100644 --- a/lib/randiso.gi +++ b/lib/randiso.gi @@ -240,6 +240,11 @@ end ); InstallGlobalFunction( CodePcgs, function( pcgs ) local code, indices, l, mi, i, base, nt, r, j, size; + # Check the argument. + if not ( IsPcgs( pcgs ) and IsPrimeOrdersPcgs( pcgs ) ) then + Error( " must be a pcgs in 'IsPrimeOrdersPcgs'" ); + fi; + # basic structures l := Length( pcgs ); if l = 0 then From 19f7a2e60570f17ed7b5781be8d793ef4db03993 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 1 Jul 2026 14:43:49 +0200 Subject: [PATCH 047/114] kernel: make FormatOutput handle %g with null pointer (#6446) In case someone uses '%g' in a format string but fails to provide a matching argument. Moreover, make sure we don't use `arg2` more then once. --- src/io.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/io.c b/src/io.c index 9484c39a01..eac2600859 100644 --- a/src/io.c +++ b/src/io.c @@ -1513,8 +1513,6 @@ static Obj FuncALL_KEYWORDS(Obj self) ** '%g' the corresponding argument is the address of a T_STRING string ** object which is printed. This is similar to using '%s' to print ** CSTR_STRING(arg), but is safe during garbage collection. -** '%G' the corresponding argument is the address of an Obj which points -** to a string in STRING_REP format which is printed in '%S' format ** '%C' the corresponding argument is the address of an Obj which points ** to a string in STRING_REP format which is printed with C escapes ** '%d' the corresponding argument is a signed integer, which is printed. @@ -1556,7 +1554,7 @@ static inline void FormatOutput( } // handle the case of a missing argument - if (arg1 == 0 && (*p == 's' || *p == 'S' || *p == 'C' || *p == 'I')) { + if (arg1 == 0 && (*p == 's' || *p == 'g' || *p == 'C' || *p == 'I')) { put_a_char(state, '<'); put_a_char(state, 'n'); put_a_char(state, 'u'); @@ -1566,6 +1564,7 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%d' print an integer @@ -1591,6 +1590,7 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%s' or '%g' print a string @@ -1650,6 +1650,7 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%C' print a string with the necessary C escapes @@ -1699,6 +1700,7 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%I' print an identifier @@ -1742,12 +1744,14 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%c' print a character else if ( *p == 'c' ) { put_a_char(state, (Char)arg1); arg1 = arg2; + arg2 = 0; } // '%%' print a '%' character From d22a930210add69fec59c3d5a7cb77d626057ff5 Mon Sep 17 00:00:00 2001 From: Thomas Breuer Date: Wed, 1 Jul 2026 15:18:55 +0200 Subject: [PATCH 048/114] turn the global variable `RUN_IN_GGMBI` into a global option `Run_In_GGMBI` (#6442) --- doc/ref/grphomom.xml | 11 ++++++++ grp/glzmodmz.gi | 8 +++--- lib/fitfree.gi | 52 ++++++++++++++++++------------------ lib/grpmat.gi | 6 ++--- lib/grpnice.gd | 3 +++ lib/grpnice.gi | 36 +++++++++++++++---------- lib/maxsub.gi | 4 +-- lib/oprt.gi | 10 +++---- lib/schursym.gi | 10 +++---- tst/testinstall/ggmbi.tst | 56 +++++++++++++++++++++++++++++++++++++++ 10 files changed, 132 insertions(+), 64 deletions(-) create mode 100644 tst/testinstall/ggmbi.tst diff --git a/doc/ref/grphomom.xml b/doc/ref/grphomom.xml index 9e4536c88a..3878ed73a0 100644 --- a/doc/ref/grphomom.xml +++ b/doc/ref/grphomom.xml @@ -372,6 +372,17 @@ are satisfied. +A technical remark:Run_In_GGMBI + +

+ +In order to avoid infinite recursions when constructing nice monomorphisms, +the global option Run_In_GGMBI is set to true in certain +situations. +The value of this option is checked in methods for the operations + and +. + <#Include Label="IsHandledByNiceMonomorphism"> <#Include Label="NiceMonomorphism"> <#Include Label="NiceObject"> diff --git a/grp/glzmodmz.gi b/grp/glzmodmz.gi index 9271ea6976..97d5e7ca77 100644 --- a/grp/glzmodmz.gi +++ b/grp/glzmodmz.gi @@ -379,7 +379,7 @@ local oper,n,R,o,nrit, if fp <>fail then # extend presentation bas:=Basis(sub,bas); - RUN_IN_GGMBI:=true; + PushOptions( rec( Run_In_GGMBI:= true ) ); hom:=GroupGeneralMappingByImagesNC(g,fp,gens,GeneratorsOfGroup(fp)); hom:=LiftFactorFpHom(hom,g,SubgroupNC(g,basm),rec( pcgs:=basm, @@ -392,7 +392,7 @@ local oper,n,R,o,nrit, return List(Coefficients(bas,e),Int); end )); - RUN_IN_GGMBI:=false; + PopOptions(); #simplify Image to avoid explosion of generator number fp:=Range(hom); if true then @@ -412,11 +412,9 @@ local oper,n,R,o,nrit, k:=TzPreImagesNewGens(e); k:=List(k,x->j[1][Position(OldGeneratorsOfPresentation(e),x)]); - RUN_IN_GGMBI:=true; hom:=GroupHomomorphismByImagesNC(g,fp, k, - GeneratorsOfGroup(fp)); - RUN_IN_GGMBI:=false; + GeneratorsOfGroup(fp) : Run_In_GGMBI:= true ); fi; SetIsomorphismFpGroup(g,hom); diff --git a/lib/fitfree.gi b/lib/fitfree.gi index a683e7964c..e8669473c0 100644 --- a/lib/fitfree.gi +++ b/lib/fitfree.gi @@ -54,10 +54,10 @@ local ffs,pcisom,rest,kpc,k,x,ker,r,pool,i,xx,pregens,iso; rest:=GroupHomomorphismByImages(U,Range(ffs.factorhom),GeneratorsOfGroup(U), List(GeneratorsOfGroup(U),x->ImagesRepresentative(ffs.factorhom,x))); else - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment rest:=GroupHomomorphismByImagesNC(U,Range(ffs.factorhom),GeneratorsOfGroup(U), List(GeneratorsOfGroup(U),x->ImagesRepresentative(ffs.factorhom,x))); - RUN_IN_GGMBI:=false; + PopOptions(); fi; Assert(1,rest<>fail); @@ -276,9 +276,9 @@ local ffs,hom,U,rest,ker,r,p,l,i,depths,pcisom,subsz,pcimgs; if IsPermGroup(U) and AssertionLevel()>1 then rest:=GroupHomomorphismByImages(U,Range(hom),gens,imgs); else - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment rest:=GroupHomomorphismByImagesNC(U,Range(hom),gens,imgs); - RUN_IN_GGMBI:=false; + PopOptions(); fi; Assert(1,rest<>fail); @@ -319,11 +319,11 @@ local ffs,hom,U,rest,ker,r,p,l,i,depths,pcisom,subsz,pcimgs; else r:=SubgroupNC(G,ipcgs); fi; - RUN_IN_GGMBI:=true; + PushOptions( rec( Run_In_GGMBI:= true ) ); pcisom:=GroupHomomorphismByImagesNC(r, SubgroupNC(Range(ffs.pcisom),pcisom), ipcgs,pcisom); - RUN_IN_GGMBI:=false; + PopOptions(); fi; r:=rec(inducedfrom:=ffs, pcgs:=ipcgs, @@ -920,10 +920,10 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs,gens; x->PreImagesRepresentativeNC(fphom,x)); sg:=List(sf,x->PreImagesRepresentativeNC(hom,x)); sp:=[]; - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(Group(sg,One(G)),fp,sg, GeneratorsOfGroup(fp)); - RUN_IN_GGMBI:=false; + PopOptions(); @@ -940,9 +940,9 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs,gens; Append(sp,mpcgs); else # extend presentation - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=LiftFactorFpHom(fphom,Source(fphom),false,mpcgs); - RUN_IN_GGMBI:=false; + PopOptions(); fp:=Image(fphom); sp:=Concatenation(sp,mpcgs); fi; @@ -954,10 +954,10 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs,gens; gens:=GeneratorsOfGroup(ocr.complement); sg:=gens{[1..Length(sg)]}; sp:=gens{[Length(sg)+1..Length(gens)]}; - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(ocr.complement,fp,gens, GeneratorsOfGroup(fp)); - RUN_IN_GGMBI:=false; + PopOptions(); fi; od; @@ -1241,11 +1241,11 @@ local s,d,c,act,o,i,j,h,p,hf,img,n,k,ns,all,hl,hcomp, # now do complements one by one for j in [1..Length(pcgs)] do h:=ClosureGroup(dser[j],gens); - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(h,fp, Concatenation(GeneratorsOfGroup(dser[j]),gens), Concatenation(List(GeneratorsOfGroup(dser[j]),x->One(fp)),imgs)); - RUN_IN_GGMBI:=false; + PopOptions(); ocr:=rec(group:=h,modulePcgs:=pcgs[j], factorfphom:=fphom); @@ -1257,18 +1257,18 @@ local s,d,c,act,o,i,j,h,p,hf,img,n,k,ns,all,hl,hcomp, if Size(b)>Size(s) then h:=ClosureGroup(b,gens); - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(h,fp, Concatenation(GeneratorsOfGroup(b),gens), Concatenation(List(GeneratorsOfGroup(b),x->One(fp)),imgs)); - RUN_IN_GGMBI:=false; + PopOptions(); # get elementary abelian series from b to s dser:=elabser(b,s); pcgs:=List([2..Length(dser)],x->ModuloPcgs(dser[x-1],dser[x])); for j in pcgs do - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=LiftFactorFpHom(fphom,Source(fphom),false,j); - RUN_IN_GGMBI:=false; + PopOptions(); od; gens:=MappingGeneratorsImages(fphom); imgs:=gens[2];gens:=gens[1]; @@ -1326,12 +1326,12 @@ local s,d,c,act,o,i,j,h,p,hf,img,n,k,ns,all,hl,hcomp, # now do complement to NS(k)/k for z in [1..Length(pcgs)] do h:=ClosureGroup(dser[z],cgens); - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(h,fp, Concatenation(GeneratorsOfGroup(dser[z]),cgens), Concatenation(List(GeneratorsOfGroup(dser[z]),x->One(fp)), imgs)); - RUN_IN_GGMBI:=false; + PopOptions(); ocr:=rec(group:=h,modulePcgs:=pcgs[z], factorfphom:=fphom); @@ -1413,10 +1413,10 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs, x->PreImagesRepresentativeNC(fphom,x)); sg:=List(sf,x->PreImagesRepresentativeNC(hom,x)); sp:=[]; - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(Group(sg,One(G)),fp,sg, GeneratorsOfGroup(fp)); - RUN_IN_GGMBI:=false; + PopOptions(); for d in [2..Length(ser.depths)] do mran:=[ser.depths[d-1]..len]; @@ -1431,9 +1431,9 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs, Append(sp,mpcgs); else # extend presentation - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=LiftFactorFpHom(fphom,Source(fphom),false,mpcgs); - RUN_IN_GGMBI:=false; + PopOptions(); fp:=Image(fphom); sp:=Concatenation(sp,mpcgs); fi; @@ -1445,10 +1445,10 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs, gens:=GeneratorsOfGroup(ocr.complement); sg:=gens{[1..Length(sg)]}; sp:=gens{[Length(sg)+1..Length(gens)]}; - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(ocr.complement,fp,gens, GeneratorsOfGroup(fp)); - RUN_IN_GGMBI:=false; + PopOptions(); fi; od; diff --git a/lib/grpmat.gi b/lib/grpmat.gi index 69966bc7a2..25d07eab9b 100644 --- a/lib/grpmat.gi +++ b/lib/grpmat.gi @@ -424,13 +424,11 @@ local field, dict, acts, start, j, zerov, zero, dim, base, partbas, heads, SetRange(hom,R); SetImagesSource(hom,R); SetMappingGeneratorsImages(hom,[acts,permimg]); -# p:=RUN_IN_GGMBI; # no niceomorphism translation here -# RUN_IN_GGMBI:=true; +# # no niceomorphism translation here # SetAsGroupGeneralMappingByImages ( hom, GroupHomomorphismByImagesNC -# ( G, R, acts, permimg ) ); +# ( G, R, acts, permimg : Run_In_GGMBI:= true ) ); # # SetFilterObj( hom, IsActionHomomorphismByBase ); -# RUN_IN_GGMBI:=p; if act=OnRight or act=OnPoints then # only store for action on right. projective action needs is own call to # `LinearActionBase' as this will set other needed parameters. diff --git a/lib/grpnice.gd b/lib/grpnice.gd index e22d72c39a..8d7dee5536 100644 --- a/lib/grpnice.gd +++ b/lib/grpnice.gd @@ -189,6 +189,9 @@ InstallSubsetMaintenance( IsHandledByNiceMonomorphism, IsHandledByNiceMonomorphism and IsGroup, IsGroup); +# We recommend the (documented) global option `Run_In_GGMBI` +# instead of the global variable `RUN_IN_GGMBI`, +# but `RUN_IN_GGMBI` is still supported because GAP packages might use it. RUN_IN_GGMBI:=false; # If somebody would call `GHBI' to make a # NiceMonomorphism, we would get an infinite recursion. # This flag can be set to avoid GHBIs to be translated diff --git a/lib/grpnice.gi b/lib/grpnice.gi index 25f7d78045..faf214a1f3 100644 --- a/lib/grpnice.gi +++ b/lib/grpnice.gi @@ -927,16 +927,22 @@ InstallMethod( GroupGeneralMappingByImagesNC, "from a group handled by a niceomorphism",true, [ IsGroup and IsHandledByNiceMonomorphism, IsGroup, IsList, IsList ], 0, function( G, H, gens, imgs ) -local nice,geni,map2,tmp; - if RUN_IN_GGMBI=true then +local nice,geni,map2; + if ValueOption( "Run_In_GGMBI" ) = true then + TryNextMethod(); + elif RUN_IN_GGMBI = true then + # Code was called that does not know about the global option. + # Make it work but print a warning. + Info( InfoWarning, 1, + "use the global option 'Run_In_GGMBI' not the global variable ", + "'RUN_IN_GGMBI', see '?Run_In_GGMBI'" ); TryNextMethod(); fi; - tmp := RUN_IN_GGMBI; - RUN_IN_GGMBI:=true; + PushOptions( rec( Run_In_GGMBI:= true ) ); nice:=RestrictedNiceMonomorphism(G); geni:=List(gens,i->ImageElm(nice,i)); map2:=GroupGeneralMappingByImagesNC(NiceObject(G),H,geni,imgs); - RUN_IN_GGMBI:=tmp; + PopOptions(); return CompositionMapping(map2,nice); end ); @@ -956,18 +962,20 @@ InstallMethod( AsGroupGeneralMappingByImages, [IsGroupGeneralMapping and IsNiceMonomorphism], {} -> RankFilter( IsHandledByNiceMonomorphism ), function(hom) -local h, tmp; - # we actually want to use the next method with `RUN_IN_GGMBI' set to + # we actually want to use the next method with `Run_In_GGMBI' set to # `true'. Therefore we redispatch, but will skip this method the second # time. - if RUN_IN_GGMBI=true then + if ValueOption( "Run_In_GGMBI" ) = true then + TryNextMethod(); + elif RUN_IN_GGMBI = true then + # Code was called that does not know about the global option. + # Make it work but print a warning. + Info( InfoWarning, 1, + "use the global option 'Run_In_GGMBI' not the global variable ", + "'RUN_IN_GGMBI', see '?Run_In_GGMBI'" ); TryNextMethod(); fi; - tmp := RUN_IN_GGMBI; - RUN_IN_GGMBI:=true; - h:=AsGroupGeneralMappingByImages(hom); - RUN_IN_GGMBI:=tmp; - return h; + return AsGroupGeneralMappingByImages( hom : Run_In_GGMBI:= true ); end); ############################################################################# @@ -980,7 +988,7 @@ InstallMethod( PreImagesRepresentativeNC, "for PBG-Niceo", [ IsPreimagesByAsGroupGeneralMappingByImages and IsNiceMonomorphism, IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) -local p, tmp; +local p; # avoid the double dispatch for `AsGroupGeneralMappingByImages' tmp := RUN_IN_GGMBI; RUN_IN_GGMBI:=true; diff --git a/lib/maxsub.gi b/lib/maxsub.gi index d9a9923d6d..c69f873028 100644 --- a/lib/maxsub.gi +++ b/lib/maxsub.gi @@ -219,10 +219,8 @@ BindGlobal("MaximalSubgroupClassesSol",function(G) # if necessary extent the fphom if homliftlevel+1 START_TEST( "ggmbi.tst" ); + +# Test the situations where the global option 'Run_In_GGMBI' occurs. +# - Print warnings when the deprecated global variable is used. +# (Do not use groups that are larger than their natural modules, +# since they could be cached.) +gap> G:= Group( [ [ 0, -1 ], [ 1, 0 ] ] );; +gap> nice:= NiceMonomorphism( G );; +gap> RUN_IN_GGMBI:= true;; +gap> AsGroupGeneralMappingByImages( nice );; +#I use the global option 'Run_In_GGMBI' not the global variable 'RUN_IN_GGMBI', see '?Run_In_GGMBI' +#I use the global option 'Run_In_GGMBI' not the global variable 'RUN_IN_GGMBI', see '?Run_In_GGMBI' +gap> G:= Group( [ [ 0, -1 ], [ 1, 0 ] ] );; +gap> gens:= GeneratorsOfGroup( G );; +gap> IsHandledByNiceMonomorphism( G ); +true +gap> GroupGeneralMappingByImagesNC( G, G, gens, gens );; +#I use the global option 'Run_In_GGMBI' not the global variable 'RUN_IN_GGMBI', see '?Run_In_GGMBI' +gap> RUN_IN_GGMBI:= false;; + +# - Run some examples where the option gets set, +# and where no other tests were available. +gap> G:= GL( IsPermGroup, 2, 5 );; +gap> U:= SL( IsPermGroup, 2, 5 );; +gap> Size( FittingFreeSubgroupSetup( G, U ).ker ); +2 + +# +gap> G:= Image( IsomorphismPermGroup( SchurCover( AlternatingGroup( 6 ) ) ) );; +gap> Size( SylowViaRadical( G, 3 ) ); +27 + +# +gap> G:= GL( IsPermGroup, 2, 5 );; +gap> Length( HallViaRadical( G, [ 2 ] ) ); +1 +gap> Length( HallViaRadical( G, [ 3 ] ) ); +1 + +# +gap> G:= SymmetricGroup( 5 );; +gap> Size( Source( EpimorphismSchurCover( G ) ) ); +240 +gap> G:= AlternatingGroup( 5 );; +gap> Size( Source( EpimorphismSchurCover( G ) ) ); +120 + +# +gap> G:= Group( Z(3) * [ [ [ 1, 1 ], [ 0, 1 ] ] ] );; +gap> Size( Image( SparseActionHomomorphism( G, +> Elements( GF(3)^2 ), [ Z(3) * [ 1, 0 ] ], OnRight ) ) ); +6 + +# +gap> STOP_TEST( "ggmbi.tst" ); From 18001cd60259ca84dc031d2b1520c254f2c6f306 Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Wed, 1 Jul 2026 09:42:08 -0700 Subject: [PATCH 049/114] Document the encoding used by CodePcGroup & PcGroupCode (#6441) --- lib/randiso.gd | 77 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 7 deletions(-) diff --git a/lib/randiso.gd b/lib/randiso.gd index 2a33d8b415..5f66f30e93 100644 --- a/lib/randiso.gd +++ b/lib/randiso.gd @@ -21,13 +21,63 @@ DeclareAttribute( "OmegaAndLowerPCentralSeries", IsGroup ); ## ## ## -## returns the code corresponding to pcgs. +## returns the non-negative integer code corresponding to the finite pcgs +## pcgs, which must be in . +## The code stores the relative orders of pcgs and +## the right hand sides of the nontrivial power and commutator relations +## of the pc presentation defined by pcgs. This integer encoding of +## pc groups underlies the group construction method described in +## . +##

+## More precisely, let +## g_1,\ldots,g_l be the entries of pcgs, and let +## r_1,\ldots,r_l be their relative orders. If l=0, +## the code is 0. Otherwise put +## m = \max_i r_i - 1. If the relative orders are not all equal, +## the first l base m digits are +## r_1-2,\ldots,r_l-2, so the relative order part is +## \sum_{i=1}^l (r_i-2)m^{l-i}. If the relative orders are all +## equal, this part is omitted; on decoding the relative orders are then +## read from the factorisation of the supplied group order. +##

+## After the relative order part comes a bit mask of length +## l(l+1)/2-1. The bits, from least significant to most +## significant, correspond first to the power relations +## g_1^{r_1},\ldots,g_{l-1}^{r_{l-1}}, and then to the +## commutators [g_j,g_i] for +## 1 \leq i < j \leq l, ordered by increasing i and, for +## fixed i, increasing j. A bit is 1 exactly when +## the corresponding right hand side is nontrivial. The final power +## relation g_l^{r_l}=1 is not stored separately. +##

+## The nontrivial right hand sides, in the same order as their set bits, +## are stored as base |G| digits, where G is the group +## generated by pcgs. If +## x = g_1^{e_1} \cdots g_l^{e_l}, with +## 0 \leq e_i < r_i, then the digit for x is +## \sum_{i=1}^l e_i\prod_{k=i+1}^l r_k. Equivalently, this is +## the zero-based position of x in the canonical list +## g_1^{e_1}\cdots g_l^{e_l}, ordered according to the +## lexicographic order of the tuples e_1,\dots,e_l. +##

+## Thus if b is m^l when the relative order part is present +## and 1 otherwise, if u is the bit mask, and if +## a_1,\ldots,a_t are the digits for the nontrivial right hand +## sides, then the complete code is +## A + b(u + 2^{l(l+1)/2-1}(a_1 + |G|a_2 + \cdots + +## |G|^{t-1}a_t)), where A is the relative order part, or +## 0 if that part is omitted. ## G := CyclicGroup(512);; +## gap> G := CyclicGroup(8);; ## gap> p := Pcgs( G );; ## gap> CodePcgs( p ); -## 162895587718739690298008513020159 +## 323 ## ]]> +## In this example the relative orders are [2,2,2], so there is +## no relative order part. The nontrivial power tails are g_2 +## and g_3, with digits 2 and 1 in the canonical +## list. Hence the code is +## 1 + 2 + 2^5(2 + 8\cdot 1) = 323. ## ## ## <#/GAPDoc> @@ -43,11 +93,15 @@ DeclareGlobalFunction( "CodePcgs" ); ## ## ## -## returns the code for a pcgs of G. +## returns the code for the pcgs returned by Pcgs for G. +## The encoding is the one described for . ## G := DihedralGroup(512);; -## gap> CodePcGroup( G ); -## 2940208627577393070560341803949986912431725641726 +## gap> G := CyclicGroup(8);; +## gap> code := CodePcGroup( G ); +## 323 +## gap> H := PcGroupCode( code, Size( G ) );; +## gap> IsCyclic( H ) and Size( H ) = Size( G ); +## true ## ]]> ## ## @@ -69,6 +123,15 @@ DeclareGlobalFunction( "CodePcGroup" ); ## otherwise anything may happen. ## Valid codes are usually obtained by one of the functions ## or . +## The inverse construction uses the integer format described for +## . The length of the pcgs, and in the case where +## all relative orders are equal also the relative orders themselves, are +## recovered from the prime factorisation of size. +##

+## The same integer format is also used by Magma's +## SmallGroupEncoding and SmallGroupDecoding, and by +## OSCAR's encode for pc groups and +## pc_group( order, code ). ## G := SmallGroup( 24, 12 );; ## gap> p := Pcgs( G );; From 4a30040fe68d2cbaca44b3026ed08015c3188e9d Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 20 May 2026 09:13:46 +0100 Subject: [PATCH 050/114] re-edited library files, adding NC --- lib/mapping.gd | 4 +- lib/mapprep.gi | 4 +- lib/vspchom.gi.changed | 2256 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 2260 insertions(+), 4 deletions(-) create mode 100644 lib/vspchom.gi.changed diff --git a/lib/mapping.gd b/lib/mapping.gd index 497fe25b85..2b391b67cb 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -751,7 +751,7 @@ DeclareAttribute( "ImagesSource", IsGeneralMapping ); ## ## is the set of preimages of the range of the general mapping map. ##

-## delegates to , +## delegates to , ## it is introduced only to store the preimage of map as attribute ## value. ## @@ -977,7 +977,7 @@ DeclareGlobalFunction( "Images" ); ## ## ## If elm is an element of the range of the general mapping -## map then returns the set of all +## map then returns the set of all ## preimages of elm under map. ##

## From &GAP; version 4.16.0 diff --git a/lib/mapprep.gi b/lib/mapprep.gi index 8b3ebe6fc2..8be5d05fc6 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -325,7 +325,7 @@ InstallMethod( PreImagesElm, [ IsCompositionMappingRep, IsObject ], 0, function( com, elm ) if not ( elm in Range(com) ) then - return []; + return fail; fi; return PreImagesElmNC( com, elm ); end ); @@ -2022,7 +2022,7 @@ InstallMethod( PreImagesElm, [ IsGeneralRestrictedMappingRep, IsObject ], 0, function( res, elm ) if not ( elm in Range(res) ) then - return []; + return fail; fi; return PreImagesElmNC( res, elm ); end ); diff --git a/lib/vspchom.gi.changed b/lib/vspchom.gi.changed new file mode 100644 index 0000000000..7fe397f6bd --- /dev/null +++ b/lib/vspchom.gi.changed @@ -0,0 +1,2256 @@ +############################################################################# +## +## This file is part of GAP, a system for computational discrete algebra. +## This file's authors include Thomas Breuer. +## +## Copyright of GAP belongs to its developers, whose names are too numerous +## to list here. Please refer to the COPYRIGHT file for details. +## +## SPDX-License-Identifier: GPL-2.0-or-later +## +## This file contains methods for general linear mappings of finite +## dimensional free left modules. +## +## There are two default representations of such general mappings, +## one by generators and images, the other by two bases and a matrix. +## +## Note that a matrix is not the appropriate object to represent a general +## linear mapping if it is not total or not single-valued; +## moreover, if one does not prescribe images of a basis but of an +## arbitrary generating system, one does not want to compute a basis at the +## time the general mapping is formed; +## finally, the matrix is not appropriate to compute preimages, whereas +## the general mapping by images behaves symmetrically in this respect. +## +## (The matrix is best for linear mappings used as arithmetic elements, +## for mapping elements of the source to the range and back; storing +## images and preimages avoids the matrix multiplication.) +## +## 1. methods for linear general mappings given by images +## 2. methods for linear mappings given by matrices +## 3. methods for vector spaces of linear mappings +## 4. methods for algebras of linear mappings +## 5. methods for full hom spaces +## + +#T TODO: +#T +#T specific representation for nat. hom. +#T (choice of coefficients instead of silly matrix) +#T AsLeftModuleGeneralMappingByImages, to allow id + id, c * id, -id, +#T Zero( id ), id + zero, - zero, c * zero, ... +#T \= methods for m.b.m. and g.m.b.i. (if bases coincide, compare data) +#T parent dependencies for nat. hom. + +#T put bases into mappings; +#T check that they are really bases of source/range! + + +############################################################################# +## +## 1. methods for linear general mappings given by images +## + +############################################################################# +## +#R IsLinearGeneralMappingByImagesDefaultRep +## +## is a default representation of $F$-linear general mappings between two +## free left modules $V$ and $W$ where $F$ is equal to the left acting +## domain of $V$ and of $W$. +## +#T (It would be possible to allow situations where $F$ is only contained +#T in the left acting domain of $W$; +#T this would lead to asymmetry w.r.t. taking the inverse general mapping.) +## +## Defining components are +## +## `generators' \: \\ +## list of vectors in $V$, +## +## `genimages' \: \\ +## list of vectors in $W$. +## +## The general mapping is defined as the linear closure of the relation +## that joins the $i$-th entry in `generators' and the $i$-th entry in +## `genimages'. +## +## If one wants to compute images, one needs the components +## `basispreimage' \: \\ +## a basis of the $F$-module generated by `generators', +## +## `imagesbasispreimage' \: \\ +## images of the basis vectors of `basispreimage', +## +## `corelations' \: \\ +## linearly independent generators for the corelation space, +## i.e., of the space of all row vectors such that +## `LinearCombination( , generators )' is zero in $V$. +## (The corresponding linear combinations of `genimages' +## generate the cokernel.) +## +## If these components are not yet bound, they are computed by +## `MakeImagesInfoLinearGeneralMappingByImages' when they are needed. +## If `generators' is a *basis* of a free left module then these +## components can be entered without extra work. +## +## If one wants to compute preimages, one needs the components +## `basisimage' \: \\ +## a basis of the $F$-module generated by `genimages', +## +## `preimagesbasisimage' \: \\ +## preimages of the basis vectors of `basisimage', +## +## `relations' \: \\ +## linearly independent generators for the relation space, +## i.e., of the space of all row vectors such that +## `LinearCombination( , genimages )' is zero in $W$. +## (The corresponding linear combinations of `generators' +## generate the kernel.) +## +## If these components are not yet bound, they are computed by +## `MakePreImagesInfoLinearGeneralMappingByImages' when they are needed. +## If `genimages' is a *basis* of a free left module then these +## components can be entered without extra work. +## +## Computed images and preimages of free left modules under linear mappings +## are always free left modules. +## If one needs more structure (e.g., that of an algebra) for an image or +## preimage then the linear mapping must have a special representation. +## +## Note that the inverse general mapping of a linear mapping defined by +## images is best handled if it uses the default method, +## since such an inverse general mapping delegates the tasks of computing +## (pre)images to the original general mapping. +## So the (pre)images info is computed only once. +#T but what about sums of such mappings? +#T better try to share info also in this case? +#T (share a list that is filled with the info later?) +## +DeclareRepresentation( "IsLinearGeneralMappingByImagesDefaultRep", + IsAttributeStoringRep, + [ "basisimage", "preimagesbasisimage", "corelations", + "basispreimage", "imagesbasispreimage", "relations", + "generators", "genimages" ] ); + +InstallTrueMethod( IsAdditiveElementWithInverse, + IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ); +InstallTrueMethod( IsLeftModuleGeneralMapping, + IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ); + + +############################################################################# +## +#M LeftModuleGeneralMappingByImages( , , , ) +## +InstallMethod( LeftModuleGeneralMappingByImages, + "for two free left modules and two homogeneous lists", + [ IsFreeLeftModule, IsFreeLeftModule, + IsHomogeneousList, IsHomogeneousList ], + function( S, R, gens, imgs ) + + local map; # general mapping from to , result + + # Check the arguments. + if Length( gens ) <> Length( imgs ) then + Error( " and must have the same length" ); + elif not IsSubset( S, gens ) then + Error( " must lie in " ); + elif not IsSubset( R, imgs ) then + Error( " must lie in " ); + elif LeftActingDomain( S ) <> LeftActingDomain( R ) then + Error( " and must have same left acting domain" ); + fi; + + # Make the general mapping. + map:= Objectify( TypeOfDefaultGeneralMapping( S, R, + IsSPGeneralMapping + and IsLeftModuleGeneralMapping + and IsLinearGeneralMappingByImagesDefaultRep ), + rec() ); + + SetMappingGeneratorsImages(map,[gens,imgs]); + # Handle the case that `gens' is a basis. + if IsBasis( gens ) then + map!.basispreimage := gens; + map!.imagesbasispreimage := imgs; + map!.corelations := Immutable( [] ); + fi; + + # Handle the case that `imgs' is a basis. + if IsBasis( imgs ) then + map!.basisimage := imgs; + map!.preimagesbasisimage := gens; + map!.relations := Immutable( [] ); + fi; + + # return the general mapping + return map; + end ); + + +############################################################################# +## +#M LeftModuleHomomorphismByImagesNC( , , , ) +## +InstallMethod( LeftModuleHomomorphismByImagesNC, + "for two left modules and two lists", + [ IsFreeLeftModule, IsFreeLeftModule, IsList, IsList ], + function( S, R, gens, imgs ) + local map; # homomorphism from to , result + map:= LeftModuleGeneralMappingByImages( S, R, gens, imgs ); + SetIsSingleValued( map, true ); + SetIsTotal( map, true ); + return map; + end ); + + +############################################################################# +## +#F LeftModuleHomomorphismByImages( , , , ) +## +InstallGlobalFunction( LeftModuleHomomorphismByImages, + function( S, R, gens, imgs ) + local hom; + hom:= LeftModuleGeneralMappingByImages( S, R, gens, imgs ); + if IsMapping( hom ) then + return LeftModuleHomomorphismByImagesNC( S, R, gens, imgs ); + else + return fail; + fi; +end ); + + +############################################################################# +## +#M AsLeftModuleGeneralMappingByImages( ) . for a lin. gen. mapping +## +InstallMethod( AsLeftModuleGeneralMappingByImages, + "for a linear g.m.b.i.", + [ IsLeftModuleGeneralMapping + and IsLinearGeneralMappingByImagesDefaultRep ], + IdFunc ); + + +############################################################################# +## +#M ImagesSource( ) . . . . . . . . . . . . . . . . for linear g.m.b.i. +## +InstallMethod( ImagesSource, + "for a linear g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + if IsBound( map!.basisimage ) then + return UnderlyingLeftModule( map!.basisimage ); + else + return SubmoduleNC( Range( map ), MappingGeneratorsImages(map)[2] ); +#T is it used that the second argument may be a basis object? + fi; + end ); + + +############################################################################# +## +#M PreImagesRange( ) . . . . . . . . . . . . . . . for linear g.m.b.i. +## +InstallMethod( PreImagesRange, + "for a linear g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + if IsBound( map!.basispreimage ) then + return UnderlyingLeftModule( map!.basispreimage ); + else + return SubmoduleNC( Source( map ), MappingGeneratorsImages(map)[1] ); +#T is it used that the second argument may be a basis object? + fi; + end ); + + +############################################################################# +## +#F MakeImagesInfoLinearGeneralMappingByImages( ) +## +## Provide the information for computing images, that is, set up +## the components `basispreimage', `imagesbasispreimage', `corelations'. +## +BindGlobal( "MakeImagesInfoLinearGeneralMappingByImages", function( map ) + local preimage, + ech, + mapi, + B; + + preimage:= PreImagesRange( map ); + mapi:= MappingGeneratorsImages( map ); + + if Dimension( preimage ) = 0 then + + # Set the entries explicitly. + map!.basispreimage := Basis( preimage ); + map!.corelations := IdentityMat( Length( mapi[2] ), + LeftActingDomain( preimage ) ); + map!.imagesbasispreimage := Immutable( [] ); + + elif IsGaussianRowSpace( Source( map ) ) then +#T operation MakeImagesInfo( map, source ) +#T to leave this to the method selection ? +#T or flag `IsFromGaussianSpace' ? + + # The images of the basis vectors are obtained on + # forming the linear combinations of images of generators + # given by `ech.coeffs'. + + ech:= SemiEchelonMatTransformation( mapi[1] ); + map!.basispreimage := SemiEchelonBasisNC( + preimage, ech.vectors ); + map!.corelations := Immutable( ech.relations ); + map!.imagesbasispreimage := Immutable( ech.coeffs * mapi[2] ); +#T problem if mapi[2] is a basis and if this does not store that it is a small list! + + else + + # Delegate the work to the associated row space. + B:= Basis( preimage ); + ech:= SemiEchelonMatTransformation( List( mapi[1], + x -> Coefficients( B, x ) ) ); + map!.basispreimage := BasisNC( preimage, + List( ech.vectors, + x -> LinearCombination( B, x ) ) ); + map!.corelations := Immutable( ech.relations ); + map!.imagesbasispreimage := Immutable( List( ech.coeffs, + x -> LinearCombination( mapi[2], x ) ) ); + + fi; +end ); + + +############################################################################# +## +#F MakePreImagesInfoLinearGeneralMappingByImages( ) +## +## Provide the information for computing preimages, that is, set up +## the components `basisimage', `preimagesbasisimage', `relations'. +## +BindGlobal( "MakePreImagesInfoLinearGeneralMappingByImages", function( map ) + local image, + ech, + mapi, + B; + + mapi:= MappingGeneratorsImages( map ); + image:= ImagesSource( map ); + + if Dimension( image ) = 0 then + + # Set the entries explicitly. + map!.basisimage := Basis( image ); + map!.relations := IdentityMat( Length( mapi[1] ), + LeftActingDomain( image ) ); + map!.preimagesbasisimage := Immutable( [] ); + + elif IsGaussianRowSpace( Range( map ) ) then + + # The preimages of the basis vectors are obtained on + # forming the linear combinations of preimages of genimages + # given by `ech.coeffs'. + ech:= SemiEchelonMatTransformation( mapi[2] ); + map!.basisimage := SemiEchelonBasisNC( image, ech.vectors ); + map!.relations := Immutable( ech.relations ); + map!.preimagesbasisimage := Immutable( ech.coeffs * mapi[1]); +#T problem if mapi[1] is a basis and if this does not store that it is a small list! + + else + + # Delegate the work to the associated row space. + B:= Basis( image ); + ech:= SemiEchelonMatTransformation( List( mapi[2], + x -> Coefficients( B, x ) ) ); + map!.basisimage := BasisNC( image, + List( ech.vectors, + x -> LinearCombination( B, x ) ) ); + map!.relations := Immutable( ech.relations ); + map!.preimagesbasisimage := Immutable( List( ech.coeffs, + row -> LinearCombination( + row, mapi[1] ) ) ); + + fi; +end ); + + +############################################################################# +## +#M CoKernelOfAdditiveGeneralMapping( ) . . . for left module g.m.b.i. +## +InstallMethod( CoKernelOfAdditiveGeneralMapping, + "for left module g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local genimages; + + # Form the linear combinations of the basis vectors for the + # corelation space with the `genimages' of `map'. + + if not IsBound( map!.corelations ) then + MakeImagesInfoLinearGeneralMappingByImages( map ); + fi; + genimages:= MappingGeneratorsImages(map)[2]; + return SubmoduleNC( Range( map ), + List( map!.corelations, + r -> LinearCombination( genimages, r ) ) ); + end ); + + +############################################################################# +## +#M IsSingleValued( ) . . . . . . . . . . . . for left module g.m.b.i. +## +InstallMethod( IsSingleValued, + "for left module g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local genimages; + + if not IsBound( map!.corelations ) then + MakeImagesInfoLinearGeneralMappingByImages( map ); + fi; + genimages:= MappingGeneratorsImages(map)[2]; + return ForAll( map!.corelations, + r -> IsZero( LinearCombination( genimages, r ) ) ); + end ); + + +############################################################################# +## +#M KernelOfAdditiveGeneralMapping( ) . . . . for left module g.m.b.i. +## +InstallMethod( KernelOfAdditiveGeneralMapping, + "for left module g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local generators; + + # Form the linear combinations of the basis vectors for the + # relation space with the `generators' of `map'. + + if not IsBound( map!.relations ) then + MakePreImagesInfoLinearGeneralMappingByImages( map ); + fi; + generators:= MappingGeneratorsImages(map)[1]; + return SubmoduleNC( Source( map ), + List( map!.relations, + r -> LinearCombination( generators, r ) ) ); + end ); + + +############################################################################# +## +#M IsInjective( ) . . . . . . . . . . . . . for left module g.m.b.i. +## +InstallMethod( IsInjective, + "for left module g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local generators; + + if not IsBound( map!.relations ) then + MakePreImagesInfoLinearGeneralMappingByImages( map ); + fi; + generators:= MappingGeneratorsImages(map)[1]; + return ForAll( map!.relations, + r -> IsZero( LinearCombination( generators, r ) ) ); + end ); + + +############################################################################# +## +#M ImagesRepresentative( , ) . . . . . for left module g.m.b.i. +## +InstallMethod( ImagesRepresentative, + "for left module g.m.b.i., and element", + FamSourceEqFamElm, + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsObject ], + function( map, elm ) + if not IsBound( map!.basispreimage ) then + MakeImagesInfoLinearGeneralMappingByImages( map ); + fi; + elm:= Coefficients( map!.basispreimage, elm ); + if elm = fail then + return fail; + elif IsEmpty( elm ) then + return Zero( Range( map ) ); + fi; + return LinearCombination( map!.imagesbasispreimage, elm ); + end ); + + +############################################################################# +## +#M PreImagesRepresentative( , ) . . . . for left module g.m.b.i. +#M PreImagesRepresentativeNC( , ) . . . for left module g.m.b.i. +## +InstallMethod( PreImagesRepresentativeNC, + "for left module g.m.b.i., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsObject ], + function( map, elm ) + if not IsBound( map!.basisimage ) then + MakePreImagesInfoLinearGeneralMappingByImages( map ); + fi; + elm:= Coefficients( map!.basisimage, elm ); + if elm = fail then + return fail; + fi; + return LinearCombination( map!.preimagesbasisimage, elm ); + end ); + +InstallMethod( PreImagesRepresentative, + "for left module g.m.b.i., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsObject ], + function( map, elm ) + if not ( elm in Image( map ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); + +############################################################################# +## +#M ViewObj( ) . . . . . . . . . . . . . . . for left module g.m.b.i. +## +InstallMethod( ViewObj, + "for a left module g.m.b.i", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local mapi; + + mapi:= MappingGeneratorsImages( map ); + View( mapi[1] ); + Print( " -> " ); + View( mapi[2] ); + end ); + + +############################################################################# +## +#M PrintObj( ) . . . . . . . . . . . . . . . for left module g.m.b.i. +## +InstallMethod( PrintObj, + "for a left module g.m.b.i", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local mapi; + + mapi:= MappingGeneratorsImages( map ); + Print( "LeftModuleGeneralMappingByImages( ", + Source( map ), ", ", Range( map ), ", ", + mapi[1], ", ", mapi[2], " )" ); + end ); + +InstallMethod( PrintObj, + "for a left module hom. b.i", + [ IsMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local mapi; + + mapi:= MappingGeneratorsImages( map ); + Print( "LeftModuleHomomorphismByImages( ", + Source( map ), ", ", Range( map ), ", ", + mapi[1], ", ", mapi[2], " )" ); + end ); + + +############################################################################# +## +#M \*( , ) . . . . . . . . . . . . for scalar and linear g.m.b.i. +## +InstallMethod( \*, + "for scalar and linear g.m.b.i.", + [ IsMultiplicativeElement, + IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( scalar, map ) + local mult, # the multiple of `map', result + mapi, # generators and images + F; # left acting domain + + # Check the scalar. + # (Maybe it is in fact another mapping, and we want to compose.) + if not IsInt( scalar ) + and not IsElmsColls( FamilyObj( scalar ), + FamilyObj( LeftActingDomain( Range( map ) ) ) ) then + TryNextMethod(); + fi; + + mapi:=MappingGeneratorsImages(map); + # Construct the linear general mapping (if possible). + mult:= LeftModuleGeneralMappingByImages( + Source( map ), Range( map ), mapi[1], + List( mapi[2], v -> scalar * v ) ); + + # Maintain info on the preimage side of the general mapping. + if IsBound( map!.basispreimage ) then + mult!.basispreimage := map!.basispreimage; + mult!.imagesbasispreimage := Immutable( + List( map!.imagesbasispreimage, v -> scalar * v ) ); + mult!.corelations := map!.corelations; + fi; + + # Being a mapping is preserved by scalar multiplication. + if HasIsSingleValued( map ) then + SetIsSingleValued( mult, IsSingleValued( map ) ); + fi; + if HasIsTotal( map ) then + SetIsTotal( mult, IsTotal( map ) ); + fi; + + # If the scalar is invertible in the left acting domain of the source + # then surjectivity and injectivity are maintained as well as the image. + F:= LeftActingDomain( Source( map ) ); + if scalar in F and IsUnit( F, scalar ) then + + if HasIsInjective( map ) then + SetIsInjective( mult, IsInjective( map ) ); + fi; + if HasIsSurjective( map ) then + SetIsSurjective( mult, IsSurjective( map ) ); + fi; + + if IsBound( map!.basisimage ) then + scalar:= Inverse( scalar ); + mult!.basisimage := map!.basisimage; + mult!.preimagesbasisimage := Immutable( + List( map!.preimagesbasisimage, v -> scalar * v ) ); + mult!.relations := map!.relations; + fi; + + fi; + + return mult; + end ); + + +############################################################################# +## +#M AdditiveInverseOp( ) . . . . . . . . . . . . . for linear g.m.b.i. +## +InstallMethod( AdditiveInverseOp, + "for linear g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local ainv, # the additive inverse of `map', result + mapi; + + mapi:=MappingGeneratorsImages(map); + # Construct the linear general mapping (if possible). + ainv:= LeftModuleGeneralMappingByImages( + Source( map ), Range( map ), mapi[1], + List( mapi[2], AdditiveInverse ) ); + + # Maintain images and preimages info. + if IsBound( map!.basispreimage ) then + ainv!.basispreimage := map!.basispreimage; + ainv!.imagesbasispreimage := Immutable( + List( map!.imagesbasispreimage, AdditiveInverse ) ); + ainv!.corelations := map!.corelations; + fi; + if IsBound( map!.basisimage ) then + ainv!.basisimage := map!.basisimage; + ainv!.preimagesbasisimage := Immutable( + List( map!.preimagesbasisimage, AdditiveInverse ) ); + ainv!.relations := map!.relations; + fi; + + # Being a mapping is preserved by scalar multiplication. + if HasIsSingleValued( map ) then + SetIsSingleValued( ainv, IsSingleValued( map ) ); + fi; + if HasIsTotal( map ) then + SetIsTotal( ainv, IsTotal( map ) ); + fi; + + # Surjectivity and injectivity are maintained. + if HasIsInjective( map ) then + SetIsInjective( ainv, IsInjective( map ) ); + fi; + if HasIsSurjective( map ) then + SetIsSurjective( ainv, IsSurjective( map ) ); + fi; + + return ainv; + end ); + + +############################################################################# +## +#T \<( , ) +## +## method for two linear mappings from Gaussian spaces, use canonical bases? +## + + +############################################################################# +## +#M CompositionMapping2( , map1> ) for left mod. hom. & lin. g.m.b.i. +## +InstallMethod( CompositionMapping2, + "for left module hom. and linear g.m.b.i.", + FamSource1EqFamRange2, + [ IsLeftModuleHomomorphism, + IsLeftModuleGeneralMapping + and IsLinearGeneralMappingByImagesDefaultRep ], + function( map2, map1 ) + local comp, # composition of and , result + mapi1, + gens, + genimages; + + # Check that the linear mappings can be composed. + + mapi1:=MappingGeneratorsImages(map1); + # Compute images for the generators of `map1'. + if IsLinearGeneralMappingByImagesDefaultRep( map2 ) + and mapi1[2] = MappingGeneratorsImages(map2)[1] then + + gens := mapi1[1]; + genimages := MappingGeneratorsImages(map2)[2]; + + else + + gens:= mapi1[1]; + genimages:= List( mapi1[2], + v -> ImagesRepresentative( map2, v ) ); + + fi; + + # Construct the linear general mapping. + comp:= LeftModuleGeneralMappingByImages( + Source( map1 ), Range( map2 ), gens, genimages ); + + # Maintain images info (only if `gens' is not a basis). + if IsLinearGeneralMappingByImagesDefaultRep( comp ) + and not IsBound( comp!.basispreimage ) + and IsBound( map1!.basispreimage ) then + comp!.basispreimage := map1!.basispreimage; + comp!.corelations := map1!.corelations; + comp!.imagesbasispreimage := Immutable( + List( map1!.imagesbasispreimage, + v -> ImagesRepresentative( map2, v ) ) ); + fi; + + # Return the composition. + return comp; + end ); + + +############################################################################# +## +#M \+( , map2> ) . . . . . . . . . . . . . . . for two linear g.m.b.i. +## +## If both general mappings respect zero, additive inverses, scalar +## multiplication then the sum also does. +## +InstallOtherMethod( \+, + "for linear g.m.b.i. and general mapping", + IsIdenticalObj, + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsGeneralMapping ], + function( map1, map2 ) + local gens, + genimages, + mapi1, + sum; + + # Check that the linear mappings can be added. + if Source( map1 ) <> Source( map2 ) + or Range( map1 ) <> Range( map2 ) then + Error( " and must have same source and range" ); + elif PreImagesRange( map1 ) <> PreImagesRange( map2 ) then + Error( " and must have same preimage" ); + fi; + + mapi1:=MappingGeneratorsImages(map1); + + if IsLinearGeneralMappingByImagesDefaultRep( map2 ) + and mapi1[1] = MappingGeneratorsImages(map2)[1] then + + # If the generators in both general mappings are the same, + # it suffices to add the images. + gens := mapi1[1]; + genimages := mapi1[2] + MappingGeneratorsImages(map2)[2]; + + else + + # Compute images of the generators of `map1' under `map2'. + # (Note that both general mappings must be described in terms of + # `generators' in order to keep the meaning of `corelations'.) + gens:= mapi1[1]; + genimages:= mapi1[2] + + List( mapi1[1], + v -> ImagesRepresentative( map2, v ) ); + + fi; + + # Construct the linear general mapping. + sum:= LeftModuleGeneralMappingByImages( + Source( map1 ), Range( map1 ), gens, genimages ); + + # Maintain images info (only if `gens' is not a basis). + if IsLinearGeneralMappingByImagesDefaultRep( sum ) + and IsLinearGeneralMappingByImagesDefaultRep( map2 ) + and not IsBound( sum!.basispreimage ) + and IsBound( map1!.basispreimage ) + and IsBound( map2!.basispreimage ) + and map1!.basispreimage = map2!.basispreimage then + sum!.basispreimage := map1!.basispreimage; + sum!.corelations := map1!.corelations; + sum!.imagesbasispreimage := + map1!.imagesbasispreimage + map2!.imagesbasispreimage; + fi; + + # Return the sum. + return sum; +end ); + +InstallOtherMethod( \+, + "for general mapping and linear g.m.b.i.", + IsIdenticalObj, + [ IsGeneralMapping, + IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map1, map2 ) + local gens, + genimages, + mapi2, + sum; + + # Check that the linear mappings can be added. + if Source( map1 ) <> Source( map2 ) + or Range( map1 ) <> Range( map2 ) then + Error( " and must have same source and range" ); + elif PreImagesRange( map1 ) <> PreImagesRange( map2 ) then + Error( " and must have same preimage" ); + fi; + + mapi2:=MappingGeneratorsImages(map2); + + if IsLinearGeneralMappingByImagesDefaultRep( map1 ) + and MappingGeneratorsImages(map1)[1]= mapi2[1] then + + # If the generators in both general mappings are the same, + # it suffices to add the images. + gens := mapi2[1]; + genimages := MappingGeneratorsImages(map1)[2] + mapi2[2]; + + else + + # Compute images of the generators of `map1' under `map2'. + # (Note that both general mappings must be described in terms of + # `generators' in order to keep the meaning of `corelations'.) + gens:= mapi2[1]; + genimages:= List( mapi2[1], + v -> ImagesRepresentative( map1, v ) ) + + mapi2[2]; + + fi; + + # Construct the linear general mapping. + sum:= LeftModuleGeneralMappingByImages( + Source( map1 ), Range( map1 ), gens, genimages ); + + # Maintain images info (only if `gens' is not a basis). + if IsLinearGeneralMappingByImagesDefaultRep( sum ) + and IsLinearGeneralMappingByImagesDefaultRep( map1 ) + and not IsBound( sum!.basispreimage ) + and IsBound( map1!.basispreimage ) + and IsBound( map2!.basispreimage ) + and map1!.basispreimage = map2!.basispreimage then + sum!.basispreimage := map1!.basispreimage; + sum!.corelations := map1!.corelations; + sum!.imagesbasispreimage := + map1!.imagesbasispreimage + map2!.imagesbasispreimage; + fi; + + # Return the sum. + return sum; +end ); + + +############################################################################# +## +#M \+( , ) . . . . . . . . . for two linear mappings by images +## +## The method for (total and single-valued general) mappings takes +## advantage from the fact that `generators' and `basispreimage' components +## need not be distinguished since the `corelations' component is empty. +## +InstallOtherMethod( \+, + "for linear m.b.i. and mapping", + IsIdenticalObj, + [ IsMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsMapping ], + function( map1, map2 ) + local gens, + genimages, + mapi1, + sum; + + # Check that the linear mappings can be added. + if Source( map1 ) <> Source( map2 ) + or Range( map1 ) <> Range( map2 ) then + Error( " and must have same source and range" ); + elif PreImagesRange( map1 ) <> PreImagesRange( map2 ) then + Error( " and must have same preimage" ); + fi; + + if IsBound( map1!.basispreimage ) then + + # Use the basis in the construction. + gens:= map1!.basispreimage; + + if IsLinearGeneralMappingByImagesDefaultRep( map2 ) + and IsBound( map2!.basispreimage ) + and map1!.basispreimage = map2!.basispreimage then + + genimages := map1!.imagesbasispreimage + map2!.imagesbasispreimage; + + else + + genimages:= map1!.imagesbasispreimage + + List( gens, + v -> ImagesRepresentative( map2, v ) ); + + fi; + + else + + mapi1:=MappingGeneratorsImages(map1); + + if IsLinearGeneralMappingByImagesDefaultRep( map2 ) + and mapi1[1] = MappingGeneratorsImages(map2)[1] then + + # If the generators in both general mappings are the same, + # it suffices to add the images. + gens := mapi1[1]; + genimages := mapi1[2] + MappingGeneratorsImages(map2)[2]; + + else + + # Compute images of the generators of `map1' under `map2'. + # (Note that both general mappings must be described in terms of + # `generators' in order to keep the meaning of `corelations'.) + gens:= mapi1[1]; + genimages:= mapi1[2] + + List( mapi1[1], + v -> ImagesRepresentative( map2, v ) ); + + fi; + fi; + + # Construct the linear mapping. + sum:= LeftModuleHomomorphismByImagesNC( + Source( map1 ), Range( map1 ), gens, genimages ); + + # Return the sum. + return sum; + end ); + +InstallOtherMethod( \+, + "for mapping and linear m.b.i.", + IsIdenticalObj, + [ IsMapping, + IsMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map1, map2 ) + local gens, + genimages, + mapi2, + sum; + + # Check that the linear mappings can be added. + if Source( map1 ) <> Source( map2 ) + or Range( map1 ) <> Range( map2 ) then + Error( " and must have same source and range" ); + elif PreImagesRange( map1 ) <> PreImagesRange( map2 ) then + Error( " and must have same preimage" ); + fi; + + if IsBound( map2!.basispreimage ) then + + # Use the basis in the construction. + gens:= map2!.basispreimage; + + if IsLinearGeneralMappingByImagesDefaultRep( map1 ) + and IsBound( map1!.basispreimage ) + and map1!.basispreimage = map2!.basispreimage then + + genimages := map1!.imagesbasispreimage + map2!.imagesbasispreimage; + + else + + genimages:= List( gens, v -> ImagesRepresentative( map1, v ) ) + + map2!.imagesbasispreimage; + + fi; + + else + + mapi2:=MappingGeneratorsImages(map2); + + if IsLinearGeneralMappingByImagesDefaultRep( map1 ) + and MappingGeneratorsImages(map1)[1] = mapi2[1] then + + # If the generators in both general mappings are the same, + # it suffices to add the images. + gens := mapi2[1]; + genimages := MappingGeneratorsImages(map1)[2] + mapi2[2]; + + else + + # Compute images of the generators of `map2' under `map1'. + # (Note that both general mappings must be described in terms of + # `generators' in order to keep the meaning of `corelations'.) + gens:= mapi2[1]; + genimages:= List( mapi2[1], + v -> ImagesRepresentative( map1, v ) ) + + mapi2[2]; + + fi; + + fi; + + # Construct the linear mapping. + sum:= LeftModuleHomomorphismByImagesNC( + Source( map1 ), Range( map1 ), gens, genimages ); + + # Return the sum. + return sum; + end ); + + +############################################################################# +## +## 2. methods for linear mappings given by matrices +## + + +############################################################################# +## +#R IsLinearMappingByMatrixDefaultRep +## +## is another default representation of $F$-linear mappings between +## two free left modules $V$ and $W$ where $F$ is equal to the left acting +## domain of $V$ and of $W$. +## +## Defining components are +## +## `basissource' \: \\ +## basis of $V$, +## +## `basisrange' \: \\ +## basis of $W$, +## +## `matrix' \: \\ +## matrix over $F$, of dimensions $\dim(V)$ times $\dim(W)$. +## +## The mapping is defined as follows. +## The image of a vector in $V$ has coefficients +## `Coefficients( !.basissource ) * !.matrix' +## w.r.t. `!.basisrange'. +## +## If one wants to compute preimages, one needs the components +## `basisimage' \: \\ +## basis of the image of , +## +## `preimagesbasisimage' \: \\ +## preimages of the basis vectors of `basisimage', +## +## `relations' \: \\ +## linearly independent generators for the relation space, +## i.e., of the left null space of `!.matrix'. +## (The corresponding linear combinations of `basissource' +## generate the kernel.) +## +## If these components are not yet bound, they are computed by +## `MakePreImagesInfoLinearMappingByMatrix'. +## +## Computed images and preimages of free left modules under linear mappings +## are always free left modules. +## If one needs more structure (e.g., that of an algebra) for an image or +## preimage then the linear mapping must have a special representation. +## +## Note that the inverse general mapping of a linear mapping defined by +## a matrix is best handled if it uses the default method, +## since such an inverse general mapping delegates the tasks of computing +## (pre)images to the original general mapping. +## So the (pre)images info is computed only once. +#T but what about sums of such mappings? +#T better try to share info also in this case? +#T (share a list that is filled with the info later?) +## +DeclareRepresentation( + "IsLinearMappingByMatrixDefaultRep", + IsAttributeStoringRep, + [ "basissource", "basisrange", "matrix", + "basisimage", "preimagesbasisimage", "relations" ] ); + +InstallTrueMethod( IsAdditiveElementWithInverse, + IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ); +InstallTrueMethod( IsLeftModuleGeneralMapping, + IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ); + + +############################################################################# +## +#M LeftModuleHomomorphismByMatrix( , ,
) +## +## is the total and single-valued linear general mapping with a basis +## of the source and
a basis of the range, and the rows of the matrix +## being the coefficients vectors of the images of w.r.t. +##
. +## +InstallMethod( LeftModuleHomomorphismByMatrix, + "for two bases of free left modules and a matrix", + [ IsBasis, IsMatrix, IsBasis ], + function( BS, matrix, BR ) + local S, R, map; + + S:= UnderlyingLeftModule( BS ); + R:= UnderlyingLeftModule( BR ); + + # Check the arguments. + if Length( BS ) <> Length( matrix ) then + Error( " and must have the same length" ); + elif Length( BR ) <> Length( matrix[1] ) then + Error( "
and [1] must have the same length" ); + elif LeftActingDomain( S ) <> LeftActingDomain( R ) then + Error( " and must have same left acting domain" ); + fi; +#T check entries of the matrix? + + # Make the mapping. + map:= Objectify( TypeOfDefaultGeneralMapping( S, R, + IsSPGeneralMapping + and IsSingleValued + and IsTotal + and IsLeftModuleGeneralMapping + and IsLinearMappingByMatrixDefaultRep ), + rec( + basissource := BS, + matrix := Immutable( matrix ), + basisrange := BR + ) ); + + # return the mapping + return map; + end ); + + +############################################################################# +## +#F MakePreImagesInfoLinearMappingByMatrix( ) +## +## Provide the information for computing preimages, that is, set up +## the components `basisimage', `preimagesbasisimage', `relations'. +## +BindGlobal( "MakePreImagesInfoLinearMappingByMatrix", function( map ) + local ech, + B; + + ech:= SemiEchelonMatTransformation( map!.matrix ); + B:= Basis( Range( map ) ); + map!.basisimage := BasisNC( ImagesSource( map ), + List( ech.vectors, + x -> LinearCombination( B, x ) ) ); + map!.relations := Immutable( ech.relations ); + + map!.preimagesbasisimage := Immutable( List( ech.coeffs, + row -> LinearCombination( + map!.basissource, row ) ) ); +end ); + + +############################################################################# +## +#M KernelOfAdditiveGeneralMapping( ) . . . . . for left module m.b.m. +## +InstallMethod( KernelOfAdditiveGeneralMapping, + "for left module m.b.m.", + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], + function( map ) + local generators, S; + + # Form the linear combinations of the basis vectors for the + # relation space with the `basissource' of `map'. + + if not IsBound( map!.relations ) then + MakePreImagesInfoLinearMappingByMatrix( map ); + fi; + generators:= BasisVectors( map!.basissource ); + S:= Source( map ); + return LeftModuleByGenerators( LeftActingDomain( S ), + List( map!.relations, + r -> LinearCombination( generators, r ) ), + Zero( S ) ); + end ); + + +############################################################################# +## +#M IsInjective( ) . . . . . . . . . . . . . . for left module m.b.m. +## +InstallMethod( IsInjective, + "for left module m.b.m.", + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], + function( map ) + local generators; + + if not IsBound( map!.relations ) then + MakePreImagesInfoLinearMappingByMatrix( map ); + fi; + generators:= BasisVectors( map!.basissource ); + return ForAll( map!.relations, + r -> IsZero( LinearCombination( generators, r ) ) ); + end ); + + +############################################################################# +## +#M ImagesRepresentative( , ) . . . . . . for left module m.b.m. +## +InstallMethod( ImagesRepresentative, + "for left module m.b.m., and element", + FamSourceEqFamElm, + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, + IsObject ], + function( map, elm ) + elm:= Coefficients( map!.basissource, elm ); + if elm <> fail then + elm:= LinearCombination( map!.basisrange, elm * map!.matrix ); + fi; + return elm; + end ); + + +############################################################################# +## +#M PreImagesRepresentativeNC( , ) . . . . for left module m.b.m. +## +InstallMethod( PreImagesRepresentativeNC, + "for left module m.b.m., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, + IsObject ], + function( map, elm ) + if not IsBound( map!.basisimage ) then + MakePreImagesInfoLinearMappingByMatrix( map ); + fi; + elm:= Coefficients( map!.basisimage, elm ); + if elm = fail then + return fail; + fi; + return LinearCombination( map!.preimagesbasisimage, elm ); + end ); + +InstallMethod( PreImagesRepresentative, + "for left module m.b.m., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, + IsObject ], + function( map, elm ) + if not ( elm in Image( map ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); + + +############################################################################# +## +#M ViewObj( ) . . . . . . . . . . . . . . . . for left module m.b.m. +## +InstallMethod( ViewObj, + "for a left module m.b.m.", + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], + function( map ) + Print( " " ); + View( UnderlyingLeftModule( map!.basisrange ) ); + Print( ">" ); + end ); + + +############################################################################# +## +#M PrintObj( ) . . . . . . . . . . . . . . . . for left module m.b.m. +## +InstallMethod( PrintObj, + "for a left module m.b.m.", + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], + function( map ) + Print( "LeftModuleHomomorphismByMatrix( ", + map!.basissource, ", ", map!.matrix, ", ", + map!.basisrange, " )" ); + end ); + + +############################################################################# +## +#M NaturalHomomorphismBySubspace( , ) . . . for free left modules +## +## Return the identity mapping. +## +InstallMethod( NaturalHomomorphismBySubspace, + "for left module and trivial left module", + IsIdenticalObj, + [ IsFreeLeftModule, IsFreeLeftModule and IsTrivial ], + SUM_FLAGS, # better than everything else + function( V, W ) + return IdentityMapping( V ); + end ); + + +############################################################################# +## +#F NaturalHomomorphismBySubspaceOntoFullRowSpace( , ) +## +InstallGlobalFunction( NaturalHomomorphismBySubspaceOntoFullRowSpace, + function( V, W ) + local F, + Wvectors, + mb, + compl, + gen, + B, + img, + canbas, + zero, + Bimgs, + nathom; + + # Check that the modules are finite dimensional. + if not IsFiniteDimensional( V ) or not IsFiniteDimensional( W ) then + TryNextMethod(); + elif not IsSubset( V, W ) then + Error( " must be contained in " ); + fi; + + # If the left acting domains are different, adjust them. + F:= LeftActingDomain( V ); + if F <> LeftActingDomain( W ) then + F:= Intersection2( F, LeftActingDomain( W ) ); + V:= AsLeftModule( F, V ); + W:= AsLeftModule( F, W ); + fi; + + # If `V' is equal to `W', return a zero mapping. + if Dimension( V ) = Dimension( W ) then + return ZeroMapping( V, FullRowModule( F, 0 ) ); + fi; + + # Compute a basis of `V' through a basis of `W'. + Wvectors:= BasisVectors( Basis( W ) ); + if IsEmpty( Wvectors ) then + mb:= MutableBasis( F, Wvectors, Zero( W ) ); + else + mb:= MutableBasis( F, Wvectors ); + fi; + compl:= []; + for gen in BasisVectors( Basis( V ) ) do + if CloseMutableBasis( mb, gen ) then + Add( compl, gen ); + fi; + od; + B:= BasisNC( V, Concatenation( Wvectors, compl ) ); + + # Compute the linear mapping by images. + img:= FullRowModule( F, Length( compl ) ); + canbas:= CanonicalBasis( img ); + zero:= Zero( img ); + Bimgs:= Concatenation( List( Wvectors, v -> zero ), + BasisVectors( canbas ) ); + nathom:= LeftModuleHomomorphismByMatrix( B, Bimgs, canbas ); +#T take a special representation for nat. hom.s, +#T (just compute coefficients, and then choose a subset ...) + SetIsSurjective( nathom, true ); + + # Enter the preimages info. + nathom!.basisimage:= canbas; + nathom!.preimagesbasisimage:= Immutable( compl ); +#T relations are not needed if the kernel is known ? + + SetKernelOfAdditiveGeneralMapping( nathom, W ); + + # Run the implications for the factor. + UseFactorRelation( V, W, img ); + + return nathom; + end ); + + +############################################################################# +## +#M NaturalHomomorphismBySubspace( , ) . . . for two free left modules +## +## return a left module m.b.m. +## +InstallMethod( NaturalHomomorphismBySubspace, + "for two finite dimensional free left modules", + IsIdenticalObj, + [ IsFreeLeftModule, IsFreeLeftModule ], + NaturalHomomorphismBySubspaceOntoFullRowSpace ); + + +############################################################################# +## +#M \*( , ) . . . . . . . . . . . . . for scalar and linear m.b.m. +## +InstallMethod( \*, + "for scalar and linear m.b.m.", + [ IsMultiplicativeElement, + IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], + function( scalar, map ) + local mult, # the multiple of `map', result + F; # left acting domain + + # Check the scalar. + # (Maybe it is in fact another mapping, and we want to compose.) + if not IsInt( scalar ) + and not IsElmsColls( FamilyObj( scalar ), + FamilyObj( LeftActingDomain( Range( map ) ) ) ) then + TryNextMethod(); + fi; + + # Construct the linear mapping (if possible). + mult:= LeftModuleHomomorphismByMatrix( + map!.basissource, + scalar * map!.matrix, + map!.basisrange ); + + # If the scalar is invertible in the left acting domain of the source + # then surjectivity and injectivity are maintained as well as the image. + F:= LeftActingDomain( Source( map ) ); + if scalar in F and IsUnit( F, scalar ) then + + if HasIsInjective( map ) then + SetIsInjective( mult, IsInjective( map ) ); + fi; + if HasIsSurjective( map ) then + SetIsSurjective( mult, IsSurjective( map ) ); + fi; + + if IsBound( map!.basisimage ) then + scalar:= Inverse( scalar ); + mult!.basisimage := map!.basisimage; + mult!.preimagesbasisimage := Immutable( + List( map!.preimagesbasisimage, v -> scalar * v ) ); + mult!.relations := map!.relations; + fi; + + fi; + + return mult; + end ); + + +############################################################################# +## +#M AdditiveInverseOp( ) . . . . . . . . . . . . . . for linear m.b.m. +## +InstallMethod( AdditiveInverseOp, + "for linear m.b.m.", + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], + function( map ) + local ainv; # the additive inverse of `map', result + + # Construct the linear general mapping (if possible). + ainv:= LeftModuleHomomorphismByMatrix( + map!.basissource, + AdditiveInverse( map!.matrix ), + map!.basisrange ); + + # Maintain preimages info. + if IsBound( map!.basisimage ) then + ainv!.basisimage := map!.basisimage; + ainv!.preimagesbasisimage := Immutable( + List( map!.preimagesbasisimage, AdditiveInverse ) ); + ainv!.relations := map!.relations; + fi; + + # Surjectivity and injectivity are maintained. + if HasIsInjective( map ) then + SetIsInjective( ainv, IsInjective( map ) ); + fi; + if HasIsSurjective( map ) then + SetIsSurjective( ainv, IsSurjective( map ) ); + fi; + + return ainv; + end ); + + +############################################################################# +## +#M CompositionMapping2( , map1> ) . for left mod. hom. & lin. m.b.m. +## +InstallMethod( CompositionMapping2, + "for left module hom. and linear m.b.m.", + FamSource1EqFamRange2, + [ IsLeftModuleHomomorphism, + IsLeftModuleHomomorphism and IsLinearMappingByMatrixDefaultRep ], + function( map2, map1 ) + local comp, # composition of and , result + BR, # basis of the range of `map2' + mat2; # matrix corresponding to `map2' + + # Compute images for the generators of `map1'. + if IsLinearMappingByMatrixDefaultRep( map2 ) + and map1!.basisrange = map2!.basissource then + + BR := map2!.basisrange; + mat2 := map2!.matrix; + + else + + BR:= Range( map2 ); + if not IsFiniteDimensional( BR ) then + TryNextMethod(); + fi; + BR:= Basis( BR ); + mat2:= List( BasisVectors( map1!.basisrange ), + v -> Coefficients( BR, ImagesRepresentative( map2, v ) ) ); + + fi; + + # Construct the linear mapping. + comp:= LeftModuleHomomorphismByMatrix( map1!.basissource, + map1!.matrix * mat2, BR ); + + # Return the composition. + return comp; + end ); + + +############################################################################# +## +#M \+( , map2> ) . . . . . . . . . . . . . . . . for two linear m.b.m. +## +## Two general mappings that respect addition can be added pointwise +## if their images are equal and their preimages are equal. +## The sum does also respect addition. +## +## If both general mappings respect zero, additive inverses, scalar +## multiplication then the sum also does. +## +BindGlobal( "SumOfMBMAndMapping", function( map1, map2 ) + local sum; + + # Check that the linear mappings can be added. + if Source( map1 ) <> Source( map2 ) + or Range( map1 ) <> Range( map2 ) then + Error( " and must have same source and range" ); + fi; + + if IsLinearMappingByMatrixDefaultRep( map2 ) + and map1!.basissource = map2!.basissource + and map1!.basisrange = map2!.basisrange then + + # If the bases in both mappings are the same, + # it suffices to add the matrices. + sum:= LeftModuleHomomorphismByMatrix( + map1!.basissource, + map1!.matrix + map2!.matrix, + map1!.basisrange ); + + else + + # Compute images of the generators of `map1' under `map2'. + sum:= LeftModuleHomomorphismByMatrix( + map1!.basissource, + map1!.matrix + + List( BasisVectors( map1!.basissource ), + v -> Coefficients( map1!.basisrange, + ImagesRepresentative( map2, v ) ) ), + map1!.basisrange ); + + fi; + + # Return the sum. + return sum; +end ); + +BindGlobal( "SumOfMappingAndMBM", function( map1, map2 ) + local sum; + + # Check that the linear mappings can be added. + if Source( map1 ) <> Source( map2 ) + or Range( map1 ) <> Range( map2 ) then + Error( " and must have same source and range" ); + fi; + + if IsLinearMappingByMatrixDefaultRep( map1 ) + and map1!.basissource = map2!.basissource + and map1!.basisrange = map2!.basisrange then + + # If the bases in both mappings are the same, + # it suffices to add the matrices. + sum:= LeftModuleHomomorphismByMatrix( + map1!.basissource, + map1!.matrix + map2!.matrix, + map1!.basisrange ); + + else + + # Compute images of the generators of `map2' under `map1'. + sum:= LeftModuleHomomorphismByMatrix( + map2!.basissource, + List( BasisVectors( map2!.basissource ), + v -> Coefficients( map2!.basisrange, + ImagesRepresentative( map1, v ) ) ) + + map2!.matrix, + map2!.basisrange ); + + fi; + + # Return the sum. + return sum; +end ); + +InstallOtherMethod( \+, + "for linear m.b.m. and mapping", + IsIdenticalObj, + [ IsMapping and IsLinearMappingByMatrixDefaultRep, + IsMapping ], + SumOfMBMAndMapping ); + +InstallOtherMethod( \+, + "for mapping and linear m.b.m.", + IsIdenticalObj, + [ IsMapping, + IsMapping and IsLinearMappingByMatrixDefaultRep ], + SumOfMappingAndMBM ); + + +############################################################################# +## +#M \+( , ) . . . . for mapping by matrix and mapping by images +## +InstallMethod( \+, + "for linear m.b.m. and linear m.b.i.", + IsIdenticalObj, + [ IsMapping and IsLinearMappingByMatrixDefaultRep, + IsMapping and IsLinearGeneralMappingByImagesDefaultRep ], + SumOfMBMAndMapping ); + +InstallMethod( \+, + "for linear m.b.i. and linear m.b.m.", + IsIdenticalObj, + [ IsMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsMapping and IsLinearMappingByMatrixDefaultRep ], + SumOfMappingAndMBM ); + + +############################################################################# +## +## 3. methods for vector spaces of linear mappings +## + + +############################################################################# +## +#M NiceFreeLeftModuleInfo( ) . . . . . . for a space of linear mappings +#M NiceVector( , ) . . for space of lin. mappings, and lin. mapping +#M UglyVector( , ) . . . for space of linear mappings, and matrix +## +InstallHandlingByNiceBasis( "IsLinearMappingsModule", rec( + detect := function( F, gens, V, zero ) + local S, R; + if not IsGeneralMappingCollection( V ) then + return false; + fi; + gens:= AsList( gens ); + if IsEmpty( gens ) then + S:= Source( zero ); + R:= Range( zero ); + else + S:= Source( gens[1] ); + R:= Range( gens[1] ); + fi; + + # Check that the mappings have left modules as source and range. + if not IsLeftModule( S ) + or not IsLeftModule( R ) + or not ForAll( gens, IsMapping ) then + return false; + fi; + + # Check that all generators have the same source and range, + # and that source and range are in fact left modules. + if ForAny( gens, map -> Source( map ) <> S ) + or ForAny( gens, map -> Range( map ) <> R ) then + return false; + fi; + return true; + end, + + NiceFreeLeftModuleInfo := function( V ) + local F, z, S, R; + F:= LeftActingDomain( V ); + z:= Zero( V ); + S:= Source( z ); + R:= Range( z ); + + # Write `S' and `R' over `F' (necessary for the nice left module). + if LeftActingDomain( S ) <> F then + S:= AsLeftModule( F, S ); + R:= AsLeftModule( F, R ); + fi; + + return rec( basissource := Basis( S ), + basisrange := Basis( R ) ); + end, + + NiceVector := function( V, v ) + local info, M, i, c; + info:= NiceFreeLeftModuleInfo( V ); + if IsLinearMappingByMatrixDefaultRep( v ) + and info.basissource = v!.basissource + and info.basisrange = v!.basisrange then + M:= v!.matrix; + else + M:= []; + for i in BasisVectors( info.basissource ) do + c:= Coefficients( info.basisrange, ImagesRepresentative( v, i ) ); + if c = fail then + return fail; + fi; + Add( M, c ); + od; + fi; + return M; + end, + + UglyVector := function( V, mat ) + local info; + info:= NiceFreeLeftModuleInfo( V ); + return LeftModuleHomomorphismByMatrix( info.basissource, + mat, info.basisrange ); + end ) ); + + +############################################################################# +## +## 4. methods for algebras of linear mappings +## + + +############################################################################# +## +#M RingByGenerators( ) . . ring generated by a list of lin. mappings +## +## If is a list of linear mappings of finite vector spaces then +## we construct a hom algebra over the prime field. +## +InstallOtherMethod( RingByGenerators, + "for a list of linear mappings of finite vector spaces", + [ IsGeneralMappingCollection ], + function( maps ) + local S; + + maps:= AsList( maps ); + if IsEmpty( maps ) then + Error( "need at least one element" ); + fi; + if not ForAll( maps, IsLeftModuleHomomorphism ) then + TryNextMethod(); + fi; + S:= Source( maps[1] ); + if IsVectorSpace( S ) + and IsFFECollection( LeftActingDomain( S ) ) then + return FLMLORByGenerators( GF( Characteristic( S ) ), maps ); + elif IsVectorSpace( S ) + and IsCyclotomicCollection( LeftActingDomain( S ) ) then + return FLMLORByGenerators( Integers, maps ); + else + TryNextMethod(); + fi; + end ); + + +############################################################################# +## +#M DefaultRingByGenerators( ) . . ring cont. a list of lin. mappings +## +## If is a list of mappings of vector spaces then +## we construct an algebra over the prime field. +## (So this may differ from the result of `RingByGenerators' if the +## characteristic is zero.) +## +InstallOtherMethod( DefaultRingByGenerators, + "for a list of linear mappings of vector spaces", + [ IsGeneralMappingCollection ], + function( maps ) + local S; + maps:= AsList( maps ); + if IsEmpty( maps ) then + Error( "need at least one element" ); + fi; + if not ForAll( maps, IsLeftModuleHomomorphism ) then + TryNextMethod(); + fi; + S:= Source( maps[1] ); + if IsVectorSpace( S ) + and IsFFECollection( LeftActingDomain( S ) ) then + return FLMLORByGenerators( GF( Characteristic( S ) ), maps ); + elif IsVectorSpace( S ) + and IsCyclotomicCollection( LeftActingDomain( S ) ) then + return FLMLORByGenerators( Rationals, maps ); + else + TryNextMethod(); + fi; + end ); + + +############################################################################# +## +#M RingWithOneByGenerators( ) . . . . . for a list of linear mappings +## +## If is a list of linear mappings of a finite vector space then +## we construct a hom algebra-with-one over the prime field. +## +InstallOtherMethod( RingWithOneByGenerators, + "for a list of linear mappings of finite vector spaces", + [ IsGeneralMappingCollection ], + function( maps ) + local S; + + maps:= AsList( maps ); + if IsEmpty( maps ) then + Error( "need at least one element" ); + fi; + if not ForAll( maps, IsLeftModuleHomomorphism ) then + TryNextMethod(); + fi; + S:= Source( maps[1] ); + if IsVectorSpace( S ) + and IsFFECollection( LeftActingDomain( S ) ) + and S = Range( maps[1] ) then + return FLMLORWithOneByGenerators( GF( Characteristic( S ) ), maps ); + elif IsVectorSpace( S ) + and IsCyclotomicCollection( LeftActingDomain( S ) ) then + return FLMLORWithOneByGenerators( Integers, maps ); + else + TryNextMethod(); + fi; + end ); + + +############################################################################# +## +#M IsGeneratorsOfFLMLOR( , ) +#M IsGeneratorsOfFLMLORWithOne( , ) +## +#T check that sources and ranges coincide: +#T if ForAny( maps, map -> Source( map ) <> S or Range( map ) <> S ) then + +#T add implication that a FLMLOR of mappings is associative! + +#T for ideals construction, inherit the info? +#T SetNiceFreeLeftModuleInfo( I, NiceFreeLeftModuleInfo( A ) ); + + +############################################################################# +## +## 5. methods for full hom spaces +## + + +############################################################################# +## +#M IsFullHomModule( V ) . . . . . . . . . . . for space of linear mappings +## +InstallMethod( IsFullHomModule, + "for space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection ], + V -> Dimension( V ) = Dimension( UnderlyingLeftModule( NiceFreeLeftModuleInfo( V ).basissource ) ) + * Dimension( UnderlyingLeftModule( NiceFreeLeftModuleInfo( V ).basisrange ) ) ); + + +############################################################################# +## +#M Dimension( ) . . . . . . . . . for full hom space of linear mappings +## +InstallMethod( Dimension, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], + V -> Dimension( UnderlyingLeftModule( NiceFreeLeftModuleInfo( V ).basissource ) ) + * Dimension( UnderlyingLeftModule( NiceFreeLeftModuleInfo( V ).basisrange ) ) ); + + +############################################################################# +## +#M Random( ) . . . . . . . . . . . for full hom space of linear mappings +## +InstallMethodWithRandomSource( Random, + "for a random source and full hom space of linear mappings", + [ IsRandomSource, IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], + function( rs, M ) + local BS, BR; + + BR:= NiceFreeLeftModuleInfo( M ); + BS:= BR.basissource; + BR:= BR.basisrange; + + return LeftModuleHomomorphismByMatrix( BS, + RandomMat( rs, + Dimension( UnderlyingLeftModule( BS ) ), + Dimension( UnderlyingLeftModule( BR ) ), + LeftActingDomain( M ) ), + BR ); + end ); + + +############################################################################# +## +#M Representative( ) . . . . . . . for full hom space of linear mappings +## +## This method is necessary for example for computing the `Zero' value of +## . Note that does in general *not* store any generators! +## +InstallMethod( Representative, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], + function( M ) + local BS, BR; + + BR:= NiceFreeLeftModuleInfo( M ); + BS:= BR.basissource; + BR:= BR.basisrange; + + return LeftModuleHomomorphismByMatrix( BS, + NullMat( Dimension( UnderlyingLeftModule( BS ) ), + Dimension( UnderlyingLeftModule( BR ) ), + LeftActingDomain( M ) ), + BR ); + end ); + + +############################################################################# +## +#M GeneratorsOfLeftModule( ) . . . for full hom space of linear mappings +## +BindGlobal( "StandardGeneratorsOfFullHomModule", function( M ) + local BS, BR, R, one, m, n, zeromat, gens, i, j, gen; + + BR:= NiceFreeLeftModuleInfo( M ); + BS:= BR.basissource; + BR:= BR.basisrange; + R:= LeftActingDomain( M ); + one:= One( R ); + m:= Dimension( UnderlyingLeftModule( BS ) ); + n:= Dimension( UnderlyingLeftModule( BR ) ); + zeromat:= NullMat( m, n, R ); + gens:= []; + for i in [ 1 .. m ] do + for j in [ 1 .. n ] do + gen:= List( zeromat, ShallowCopy ); + gen[i][j]:= one; + Add( gens, LeftModuleHomomorphismByMatrix( BS, gen, BR ) ); + od; + od; + + return gens; +end ); + +InstallMethod( GeneratorsOfLeftModule, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], + StandardGeneratorsOfFullHomModule ); + + +############################################################################# +## +#M NiceFreeLeftModule( ) . . . . . for full hom space of linear mappings +## +## We need a special method since we decided not to store vector space +## generators in full hom spaces; +## note that the default methods for `NiceFreeLeftModule' are installed with +## requirement `HasGeneratorsOfLeftModule'. +## +InstallMethod( NiceFreeLeftModule, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], + function( M ) + if HasGeneratorsOfLeftModule( M ) then + TryNextMethod(); + fi; + GeneratorsOfLeftModule( M ); + if not HasGeneratorsOfLeftModule( M ) then + TryNextMethod(); + fi; + return NiceFreeLeftModule( M ); + end ); + + +############################################################################# +## +#M ViewObj( ) . . . . . . . . . . for full hom space of linear mappings +#M PrintObj( ) . . . . . . . . . . for full hom space of linear mappings +## +BindGlobal( "ViewFullHomModule", function( M ) + local info; + + info:= NiceFreeLeftModuleInfo( M ); + if IsIdenticalObj( info.basissource, info.basisrange ) then + Print( "End( " ); + View( LeftActingDomain( M ) ); + Print( ", " ); + View( UnderlyingLeftModule( info.basissource ) ); + Print( " )" ); + else + Print( "Hom( " ); + View( LeftActingDomain( M ) ); + Print( ", " ); + View( UnderlyingLeftModule( info.basissource ) ); + Print( ", " ); + View( UnderlyingLeftModule( info.basisrange ) ); + Print( " )" ); + fi; +end ); + +InstallMethod( ViewObj, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], SUM_FLAGS, + ViewFullHomModule ); + +InstallMethod( PrintObj, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], SUM_FLAGS, + ViewFullHomModule ); + + +############################################################################# +## +#M \in( , ) . . . . . . . . . . for full hom space of linear mappings +## +InstallMethod( \in, + "for full hom space of linear mappings", + IsElmsColls, + [ IsGeneralMapping, + IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], + function( map, M ) + local info; + info:= NiceFreeLeftModuleInfo( M ); + return Source( map ) = UnderlyingLeftModule( info.basissource ) + and Range( map ) = UnderlyingLeftModule( info.basisrange ) + and IsLeftModuleHomomorphism( map ); + end ); + + +############################################################################# +## +#M IsPseudoCanonicalBasisFullHomModule( ) . . . . for a full hom module +## +InstallMethod( IsPseudoCanonicalBasisFullHomModule, + "for a basis of a full hom module", + [ IsBasis ], + function( B ) + local V; + + V:= UnderlyingLeftModule( B ); + if IsGeneralMappingCollection( V ) then + if not IsFullHomModule( V ) then + return false; + fi; + return BasisVectors( B ) = StandardGeneratorsOfFullHomModule( V ); + else + Error( "do not know what a pseudo canon. basis for is" ); + fi; + end ); + + +############################################################################# +## +#M BasisVectors( ) . . . for pseudo canonical basis of a full hom module +## +InstallMethod( BasisVectors, + "for pseudo canonical basis of a full hom module", + [ IsBasis and IsPseudoCanonicalBasisFullHomModule ], + B -> StandardGeneratorsOfFullHomModule( UnderlyingLeftModule( B ) ) ); + + +############################################################################# +## +#M Coefficients( , ) for a pseudo canon. basis of a full hom module +## +InstallOtherMethod( Coefficients, + "for pseudo canon. basis of a full hom module, and lin. mapping", + IsCollsElms, + [ IsBasis and IsPseudoCanonicalBasisFullHomModule, IsGeneralMapping ], + function( B, map ) + local V, info; + V:= UnderlyingLeftModule( B ); + if not IsGeneralMappingCollection( V ) then + TryNextMethod(); + fi; + info:= NiceFreeLeftModuleInfo( V ); + if Source( map ) = UnderlyingLeftModule( info.basissource ) + and Range( map ) = UnderlyingLeftModule( info.basisrange ) + and IsLeftModuleHomomorphism( map ) then + return Concatenation( + List( BasisVectors( info.basissource ), + v -> Coefficients( info.basisrange, + ImagesRepresentative( map, v ) ) ) ); + else + return fail; + fi; + end ); + +InstallMethod( Coefficients, + "for pseudo can. basis of full hom module, and lin. m.b.m.", + IsCollsElms, + [ IsBasis and IsPseudoCanonicalBasisFullHomModule, + IsMapping and IsLinearMappingByMatrixDefaultRep ], + function( B, map ) + local V, info; + V:= UnderlyingLeftModule( B ); + if not IsGeneralMappingCollection( V ) then + TryNextMethod(); + fi; + info:= NiceFreeLeftModuleInfo( V ); + if map!.basissource = info.basissource + and map!.basisrange = info.basisrange then + return Concatenation( map!.matrix ); + elif Source( map ) = UnderlyingLeftModule( info.basissource ) + and Range( map ) = UnderlyingLeftModule( info.basisrange ) then + return Concatenation( + List( BasisVectors( info.basissource ), + v -> Coefficients( info.basisrange, + ImagesRepresentative( map, v ) ) ) ); + else + return fail; + fi; + end ); + + +############################################################################# +## +#M Basis( ) . . . . . . . . . . . . . . . . . . . . for full hom module +## +InstallMethod( Basis, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsFullHomModule ], 100, + function( V ) + local B; + B:= Objectify( NewType( FamilyObj( V ), + IsFiniteBasisDefault + and IsPseudoCanonicalBasisFullHomModule + and IsAttributeStoringRep ), + rec() ); + SetUnderlyingLeftModule( B, V ); + if IsFiniteDimensional( V ) then + SetIsFinite( B, true ); + #T Check whether its is a) correct and even if so + #T b) sometimes to expensive + SetBasisVectors( B, GeneratorsOfLeftModule(V) ); + fi; + return B; + end ); + + +############################################################################# +## +#M Hom( , , ) +## +InstallMethod( Hom, + "for division ring and two free left modules", + [ IsDivisionRing, IsFreeLeftModule, IsFreeLeftModule ], + function( F, V, W ) + local M; # the free module record, result + + if V = W then + return End( F, V ); + fi; + if LeftActingDomain( V ) <> F then + V:= AsLeftModule( F, V ); + fi; + if LeftActingDomain( W ) <> F then + W:= AsLeftModule( F, W ); + fi; + + M:= Objectify( NewType( CollectionsFamily( GeneralMappingsFamily( + ElementsFamily( FamilyObj( V ) ), + ElementsFamily( FamilyObj( W ) ) ) ), + IsFreeLeftModule + and IsFullHomModule + and IsLinearMappingsModule + and IsGeneralMappingCollection + and IsAttributeStoringRep ), + rec() ); + + SetLeftActingDomain( M, F ); + SetNiceFreeLeftModuleInfo( M, rec( + basissource := Basis( V ), + basisrange := Basis( W ) ) ); + + return M; + end ); + + +############################################################################# +## +#M End( , ) . . . . . . . . . for division ring and free left module +## +## We use the generators that are also taken for full matrix FLMLORs. +## +InstallMethod( End, + "for division ring and space of linear mappings", + [ IsDivisionRing, IsFreeLeftModule ], + function( F, V ) + local n, # dimension of `V' + i, # loop over the rows + gens, # list of generators + one, # the identity of the field + B, # basis of `V' + A; # algebra, result + + if LeftActingDomain( V ) <> F then + V:= AsLeftModule( F, V ); + fi; + + n:= Dimension( V ); + gens:= NullMat( n, n, F ); + gens:= [ gens, List( gens, ShallowCopy ) ]; + one:= One( F ); + + # Construct the generators. + gens[1][1][1]:= one; + gens[2][1][n]:= one; + for i in [ 2 .. n ] do + gens[2][i][i-1]:= one; + od; + B:= Basis( V ); + gens:= List( gens, mat -> LeftModuleHomomorphismByMatrix( B, mat, B ) ); + + # Construct the FLMLOR. + A:= AlgebraWithOneByGenerators( F, gens ); + SetIsFullHomModule( A, true ); + SetNiceFreeLeftModuleInfo( A, rec( + basissource := B, + basisrange := B ) ); + + # Return the FLMLOR. + return A; + end ); + + +#T InstallMethod( Field, true, [ IsGeneralMappingCollection ], 0, ... ); +#T InstallMethod( DefaultField, true, [ IsGeneralMappingCollection ], 0, ... ); From ca8a6cab8bca7a27a77308f0cc2cb5240bd8b252 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Mon, 6 Jul 2026 09:50:25 +0100 Subject: [PATCH 051/114] removed unwanted .changed file --- lib/vspchom.gi.changed | 2256 ---------------------------------------- 1 file changed, 2256 deletions(-) delete mode 100644 lib/vspchom.gi.changed diff --git a/lib/vspchom.gi.changed b/lib/vspchom.gi.changed deleted file mode 100644 index 7fe397f6bd..0000000000 --- a/lib/vspchom.gi.changed +++ /dev/null @@ -1,2256 +0,0 @@ -############################################################################# -## -## This file is part of GAP, a system for computational discrete algebra. -## This file's authors include Thomas Breuer. -## -## Copyright of GAP belongs to its developers, whose names are too numerous -## to list here. Please refer to the COPYRIGHT file for details. -## -## SPDX-License-Identifier: GPL-2.0-or-later -## -## This file contains methods for general linear mappings of finite -## dimensional free left modules. -## -## There are two default representations of such general mappings, -## one by generators and images, the other by two bases and a matrix. -## -## Note that a matrix is not the appropriate object to represent a general -## linear mapping if it is not total or not single-valued; -## moreover, if one does not prescribe images of a basis but of an -## arbitrary generating system, one does not want to compute a basis at the -## time the general mapping is formed; -## finally, the matrix is not appropriate to compute preimages, whereas -## the general mapping by images behaves symmetrically in this respect. -## -## (The matrix is best for linear mappings used as arithmetic elements, -## for mapping elements of the source to the range and back; storing -## images and preimages avoids the matrix multiplication.) -## -## 1. methods for linear general mappings given by images -## 2. methods for linear mappings given by matrices -## 3. methods for vector spaces of linear mappings -## 4. methods for algebras of linear mappings -## 5. methods for full hom spaces -## - -#T TODO: -#T -#T specific representation for nat. hom. -#T (choice of coefficients instead of silly matrix) -#T AsLeftModuleGeneralMappingByImages, to allow id + id, c * id, -id, -#T Zero( id ), id + zero, - zero, c * zero, ... -#T \= methods for m.b.m. and g.m.b.i. (if bases coincide, compare data) -#T parent dependencies for nat. hom. - -#T put bases into mappings; -#T check that they are really bases of source/range! - - -############################################################################# -## -## 1. methods for linear general mappings given by images -## - -############################################################################# -## -#R IsLinearGeneralMappingByImagesDefaultRep -## -## is a default representation of $F$-linear general mappings between two -## free left modules $V$ and $W$ where $F$ is equal to the left acting -## domain of $V$ and of $W$. -## -#T (It would be possible to allow situations where $F$ is only contained -#T in the left acting domain of $W$; -#T this would lead to asymmetry w.r.t. taking the inverse general mapping.) -## -## Defining components are -## -## `generators' \: \\ -## list of vectors in $V$, -## -## `genimages' \: \\ -## list of vectors in $W$. -## -## The general mapping is defined as the linear closure of the relation -## that joins the $i$-th entry in `generators' and the $i$-th entry in -## `genimages'. -## -## If one wants to compute images, one needs the components -## `basispreimage' \: \\ -## a basis of the $F$-module generated by `generators', -## -## `imagesbasispreimage' \: \\ -## images of the basis vectors of `basispreimage', -## -## `corelations' \: \\ -## linearly independent generators for the corelation space, -## i.e., of the space of all row vectors such that -## `LinearCombination( , generators )' is zero in $V$. -## (The corresponding linear combinations of `genimages' -## generate the cokernel.) -## -## If these components are not yet bound, they are computed by -## `MakeImagesInfoLinearGeneralMappingByImages' when they are needed. -## If `generators' is a *basis* of a free left module then these -## components can be entered without extra work. -## -## If one wants to compute preimages, one needs the components -## `basisimage' \: \\ -## a basis of the $F$-module generated by `genimages', -## -## `preimagesbasisimage' \: \\ -## preimages of the basis vectors of `basisimage', -## -## `relations' \: \\ -## linearly independent generators for the relation space, -## i.e., of the space of all row vectors such that -## `LinearCombination( , genimages )' is zero in $W$. -## (The corresponding linear combinations of `generators' -## generate the kernel.) -## -## If these components are not yet bound, they are computed by -## `MakePreImagesInfoLinearGeneralMappingByImages' when they are needed. -## If `genimages' is a *basis* of a free left module then these -## components can be entered without extra work. -## -## Computed images and preimages of free left modules under linear mappings -## are always free left modules. -## If one needs more structure (e.g., that of an algebra) for an image or -## preimage then the linear mapping must have a special representation. -## -## Note that the inverse general mapping of a linear mapping defined by -## images is best handled if it uses the default method, -## since such an inverse general mapping delegates the tasks of computing -## (pre)images to the original general mapping. -## So the (pre)images info is computed only once. -#T but what about sums of such mappings? -#T better try to share info also in this case? -#T (share a list that is filled with the info later?) -## -DeclareRepresentation( "IsLinearGeneralMappingByImagesDefaultRep", - IsAttributeStoringRep, - [ "basisimage", "preimagesbasisimage", "corelations", - "basispreimage", "imagesbasispreimage", "relations", - "generators", "genimages" ] ); - -InstallTrueMethod( IsAdditiveElementWithInverse, - IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ); -InstallTrueMethod( IsLeftModuleGeneralMapping, - IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ); - - -############################################################################# -## -#M LeftModuleGeneralMappingByImages( , , , ) -## -InstallMethod( LeftModuleGeneralMappingByImages, - "for two free left modules and two homogeneous lists", - [ IsFreeLeftModule, IsFreeLeftModule, - IsHomogeneousList, IsHomogeneousList ], - function( S, R, gens, imgs ) - - local map; # general mapping from to , result - - # Check the arguments. - if Length( gens ) <> Length( imgs ) then - Error( " and must have the same length" ); - elif not IsSubset( S, gens ) then - Error( " must lie in " ); - elif not IsSubset( R, imgs ) then - Error( " must lie in " ); - elif LeftActingDomain( S ) <> LeftActingDomain( R ) then - Error( " and must have same left acting domain" ); - fi; - - # Make the general mapping. - map:= Objectify( TypeOfDefaultGeneralMapping( S, R, - IsSPGeneralMapping - and IsLeftModuleGeneralMapping - and IsLinearGeneralMappingByImagesDefaultRep ), - rec() ); - - SetMappingGeneratorsImages(map,[gens,imgs]); - # Handle the case that `gens' is a basis. - if IsBasis( gens ) then - map!.basispreimage := gens; - map!.imagesbasispreimage := imgs; - map!.corelations := Immutable( [] ); - fi; - - # Handle the case that `imgs' is a basis. - if IsBasis( imgs ) then - map!.basisimage := imgs; - map!.preimagesbasisimage := gens; - map!.relations := Immutable( [] ); - fi; - - # return the general mapping - return map; - end ); - - -############################################################################# -## -#M LeftModuleHomomorphismByImagesNC( , , , ) -## -InstallMethod( LeftModuleHomomorphismByImagesNC, - "for two left modules and two lists", - [ IsFreeLeftModule, IsFreeLeftModule, IsList, IsList ], - function( S, R, gens, imgs ) - local map; # homomorphism from to , result - map:= LeftModuleGeneralMappingByImages( S, R, gens, imgs ); - SetIsSingleValued( map, true ); - SetIsTotal( map, true ); - return map; - end ); - - -############################################################################# -## -#F LeftModuleHomomorphismByImages( , , , ) -## -InstallGlobalFunction( LeftModuleHomomorphismByImages, - function( S, R, gens, imgs ) - local hom; - hom:= LeftModuleGeneralMappingByImages( S, R, gens, imgs ); - if IsMapping( hom ) then - return LeftModuleHomomorphismByImagesNC( S, R, gens, imgs ); - else - return fail; - fi; -end ); - - -############################################################################# -## -#M AsLeftModuleGeneralMappingByImages( ) . for a lin. gen. mapping -## -InstallMethod( AsLeftModuleGeneralMappingByImages, - "for a linear g.m.b.i.", - [ IsLeftModuleGeneralMapping - and IsLinearGeneralMappingByImagesDefaultRep ], - IdFunc ); - - -############################################################################# -## -#M ImagesSource( ) . . . . . . . . . . . . . . . . for linear g.m.b.i. -## -InstallMethod( ImagesSource, - "for a linear g.m.b.i.", - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( map ) - if IsBound( map!.basisimage ) then - return UnderlyingLeftModule( map!.basisimage ); - else - return SubmoduleNC( Range( map ), MappingGeneratorsImages(map)[2] ); -#T is it used that the second argument may be a basis object? - fi; - end ); - - -############################################################################# -## -#M PreImagesRange( ) . . . . . . . . . . . . . . . for linear g.m.b.i. -## -InstallMethod( PreImagesRange, - "for a linear g.m.b.i.", - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( map ) - if IsBound( map!.basispreimage ) then - return UnderlyingLeftModule( map!.basispreimage ); - else - return SubmoduleNC( Source( map ), MappingGeneratorsImages(map)[1] ); -#T is it used that the second argument may be a basis object? - fi; - end ); - - -############################################################################# -## -#F MakeImagesInfoLinearGeneralMappingByImages( ) -## -## Provide the information for computing images, that is, set up -## the components `basispreimage', `imagesbasispreimage', `corelations'. -## -BindGlobal( "MakeImagesInfoLinearGeneralMappingByImages", function( map ) - local preimage, - ech, - mapi, - B; - - preimage:= PreImagesRange( map ); - mapi:= MappingGeneratorsImages( map ); - - if Dimension( preimage ) = 0 then - - # Set the entries explicitly. - map!.basispreimage := Basis( preimage ); - map!.corelations := IdentityMat( Length( mapi[2] ), - LeftActingDomain( preimage ) ); - map!.imagesbasispreimage := Immutable( [] ); - - elif IsGaussianRowSpace( Source( map ) ) then -#T operation MakeImagesInfo( map, source ) -#T to leave this to the method selection ? -#T or flag `IsFromGaussianSpace' ? - - # The images of the basis vectors are obtained on - # forming the linear combinations of images of generators - # given by `ech.coeffs'. - - ech:= SemiEchelonMatTransformation( mapi[1] ); - map!.basispreimage := SemiEchelonBasisNC( - preimage, ech.vectors ); - map!.corelations := Immutable( ech.relations ); - map!.imagesbasispreimage := Immutable( ech.coeffs * mapi[2] ); -#T problem if mapi[2] is a basis and if this does not store that it is a small list! - - else - - # Delegate the work to the associated row space. - B:= Basis( preimage ); - ech:= SemiEchelonMatTransformation( List( mapi[1], - x -> Coefficients( B, x ) ) ); - map!.basispreimage := BasisNC( preimage, - List( ech.vectors, - x -> LinearCombination( B, x ) ) ); - map!.corelations := Immutable( ech.relations ); - map!.imagesbasispreimage := Immutable( List( ech.coeffs, - x -> LinearCombination( mapi[2], x ) ) ); - - fi; -end ); - - -############################################################################# -## -#F MakePreImagesInfoLinearGeneralMappingByImages( ) -## -## Provide the information for computing preimages, that is, set up -## the components `basisimage', `preimagesbasisimage', `relations'. -## -BindGlobal( "MakePreImagesInfoLinearGeneralMappingByImages", function( map ) - local image, - ech, - mapi, - B; - - mapi:= MappingGeneratorsImages( map ); - image:= ImagesSource( map ); - - if Dimension( image ) = 0 then - - # Set the entries explicitly. - map!.basisimage := Basis( image ); - map!.relations := IdentityMat( Length( mapi[1] ), - LeftActingDomain( image ) ); - map!.preimagesbasisimage := Immutable( [] ); - - elif IsGaussianRowSpace( Range( map ) ) then - - # The preimages of the basis vectors are obtained on - # forming the linear combinations of preimages of genimages - # given by `ech.coeffs'. - ech:= SemiEchelonMatTransformation( mapi[2] ); - map!.basisimage := SemiEchelonBasisNC( image, ech.vectors ); - map!.relations := Immutable( ech.relations ); - map!.preimagesbasisimage := Immutable( ech.coeffs * mapi[1]); -#T problem if mapi[1] is a basis and if this does not store that it is a small list! - - else - - # Delegate the work to the associated row space. - B:= Basis( image ); - ech:= SemiEchelonMatTransformation( List( mapi[2], - x -> Coefficients( B, x ) ) ); - map!.basisimage := BasisNC( image, - List( ech.vectors, - x -> LinearCombination( B, x ) ) ); - map!.relations := Immutable( ech.relations ); - map!.preimagesbasisimage := Immutable( List( ech.coeffs, - row -> LinearCombination( - row, mapi[1] ) ) ); - - fi; -end ); - - -############################################################################# -## -#M CoKernelOfAdditiveGeneralMapping( ) . . . for left module g.m.b.i. -## -InstallMethod( CoKernelOfAdditiveGeneralMapping, - "for left module g.m.b.i.", - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( map ) - local genimages; - - # Form the linear combinations of the basis vectors for the - # corelation space with the `genimages' of `map'. - - if not IsBound( map!.corelations ) then - MakeImagesInfoLinearGeneralMappingByImages( map ); - fi; - genimages:= MappingGeneratorsImages(map)[2]; - return SubmoduleNC( Range( map ), - List( map!.corelations, - r -> LinearCombination( genimages, r ) ) ); - end ); - - -############################################################################# -## -#M IsSingleValued( ) . . . . . . . . . . . . for left module g.m.b.i. -## -InstallMethod( IsSingleValued, - "for left module g.m.b.i.", - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( map ) - local genimages; - - if not IsBound( map!.corelations ) then - MakeImagesInfoLinearGeneralMappingByImages( map ); - fi; - genimages:= MappingGeneratorsImages(map)[2]; - return ForAll( map!.corelations, - r -> IsZero( LinearCombination( genimages, r ) ) ); - end ); - - -############################################################################# -## -#M KernelOfAdditiveGeneralMapping( ) . . . . for left module g.m.b.i. -## -InstallMethod( KernelOfAdditiveGeneralMapping, - "for left module g.m.b.i.", - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( map ) - local generators; - - # Form the linear combinations of the basis vectors for the - # relation space with the `generators' of `map'. - - if not IsBound( map!.relations ) then - MakePreImagesInfoLinearGeneralMappingByImages( map ); - fi; - generators:= MappingGeneratorsImages(map)[1]; - return SubmoduleNC( Source( map ), - List( map!.relations, - r -> LinearCombination( generators, r ) ) ); - end ); - - -############################################################################# -## -#M IsInjective( ) . . . . . . . . . . . . . for left module g.m.b.i. -## -InstallMethod( IsInjective, - "for left module g.m.b.i.", - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( map ) - local generators; - - if not IsBound( map!.relations ) then - MakePreImagesInfoLinearGeneralMappingByImages( map ); - fi; - generators:= MappingGeneratorsImages(map)[1]; - return ForAll( map!.relations, - r -> IsZero( LinearCombination( generators, r ) ) ); - end ); - - -############################################################################# -## -#M ImagesRepresentative( , ) . . . . . for left module g.m.b.i. -## -InstallMethod( ImagesRepresentative, - "for left module g.m.b.i., and element", - FamSourceEqFamElm, - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, - IsObject ], - function( map, elm ) - if not IsBound( map!.basispreimage ) then - MakeImagesInfoLinearGeneralMappingByImages( map ); - fi; - elm:= Coefficients( map!.basispreimage, elm ); - if elm = fail then - return fail; - elif IsEmpty( elm ) then - return Zero( Range( map ) ); - fi; - return LinearCombination( map!.imagesbasispreimage, elm ); - end ); - - -############################################################################# -## -#M PreImagesRepresentative( , ) . . . . for left module g.m.b.i. -#M PreImagesRepresentativeNC( , ) . . . for left module g.m.b.i. -## -InstallMethod( PreImagesRepresentativeNC, - "for left module g.m.b.i., and element", - FamRangeEqFamElm, - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, - IsObject ], - function( map, elm ) - if not IsBound( map!.basisimage ) then - MakePreImagesInfoLinearGeneralMappingByImages( map ); - fi; - elm:= Coefficients( map!.basisimage, elm ); - if elm = fail then - return fail; - fi; - return LinearCombination( map!.preimagesbasisimage, elm ); - end ); - -InstallMethod( PreImagesRepresentative, - "for left module g.m.b.i., and element", - FamRangeEqFamElm, - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, - IsObject ], - function( map, elm ) - if not ( elm in Image( map ) ) then - return fail; - fi; - return PreImagesRepresentativeNC( map, elm ); - end ); - -############################################################################# -## -#M ViewObj( ) . . . . . . . . . . . . . . . for left module g.m.b.i. -## -InstallMethod( ViewObj, - "for a left module g.m.b.i", - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( map ) - local mapi; - - mapi:= MappingGeneratorsImages( map ); - View( mapi[1] ); - Print( " -> " ); - View( mapi[2] ); - end ); - - -############################################################################# -## -#M PrintObj( ) . . . . . . . . . . . . . . . for left module g.m.b.i. -## -InstallMethod( PrintObj, - "for a left module g.m.b.i", - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( map ) - local mapi; - - mapi:= MappingGeneratorsImages( map ); - Print( "LeftModuleGeneralMappingByImages( ", - Source( map ), ", ", Range( map ), ", ", - mapi[1], ", ", mapi[2], " )" ); - end ); - -InstallMethod( PrintObj, - "for a left module hom. b.i", - [ IsMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( map ) - local mapi; - - mapi:= MappingGeneratorsImages( map ); - Print( "LeftModuleHomomorphismByImages( ", - Source( map ), ", ", Range( map ), ", ", - mapi[1], ", ", mapi[2], " )" ); - end ); - - -############################################################################# -## -#M \*( , ) . . . . . . . . . . . . for scalar and linear g.m.b.i. -## -InstallMethod( \*, - "for scalar and linear g.m.b.i.", - [ IsMultiplicativeElement, - IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( scalar, map ) - local mult, # the multiple of `map', result - mapi, # generators and images - F; # left acting domain - - # Check the scalar. - # (Maybe it is in fact another mapping, and we want to compose.) - if not IsInt( scalar ) - and not IsElmsColls( FamilyObj( scalar ), - FamilyObj( LeftActingDomain( Range( map ) ) ) ) then - TryNextMethod(); - fi; - - mapi:=MappingGeneratorsImages(map); - # Construct the linear general mapping (if possible). - mult:= LeftModuleGeneralMappingByImages( - Source( map ), Range( map ), mapi[1], - List( mapi[2], v -> scalar * v ) ); - - # Maintain info on the preimage side of the general mapping. - if IsBound( map!.basispreimage ) then - mult!.basispreimage := map!.basispreimage; - mult!.imagesbasispreimage := Immutable( - List( map!.imagesbasispreimage, v -> scalar * v ) ); - mult!.corelations := map!.corelations; - fi; - - # Being a mapping is preserved by scalar multiplication. - if HasIsSingleValued( map ) then - SetIsSingleValued( mult, IsSingleValued( map ) ); - fi; - if HasIsTotal( map ) then - SetIsTotal( mult, IsTotal( map ) ); - fi; - - # If the scalar is invertible in the left acting domain of the source - # then surjectivity and injectivity are maintained as well as the image. - F:= LeftActingDomain( Source( map ) ); - if scalar in F and IsUnit( F, scalar ) then - - if HasIsInjective( map ) then - SetIsInjective( mult, IsInjective( map ) ); - fi; - if HasIsSurjective( map ) then - SetIsSurjective( mult, IsSurjective( map ) ); - fi; - - if IsBound( map!.basisimage ) then - scalar:= Inverse( scalar ); - mult!.basisimage := map!.basisimage; - mult!.preimagesbasisimage := Immutable( - List( map!.preimagesbasisimage, v -> scalar * v ) ); - mult!.relations := map!.relations; - fi; - - fi; - - return mult; - end ); - - -############################################################################# -## -#M AdditiveInverseOp( ) . . . . . . . . . . . . . for linear g.m.b.i. -## -InstallMethod( AdditiveInverseOp, - "for linear g.m.b.i.", - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( map ) - local ainv, # the additive inverse of `map', result - mapi; - - mapi:=MappingGeneratorsImages(map); - # Construct the linear general mapping (if possible). - ainv:= LeftModuleGeneralMappingByImages( - Source( map ), Range( map ), mapi[1], - List( mapi[2], AdditiveInverse ) ); - - # Maintain images and preimages info. - if IsBound( map!.basispreimage ) then - ainv!.basispreimage := map!.basispreimage; - ainv!.imagesbasispreimage := Immutable( - List( map!.imagesbasispreimage, AdditiveInverse ) ); - ainv!.corelations := map!.corelations; - fi; - if IsBound( map!.basisimage ) then - ainv!.basisimage := map!.basisimage; - ainv!.preimagesbasisimage := Immutable( - List( map!.preimagesbasisimage, AdditiveInverse ) ); - ainv!.relations := map!.relations; - fi; - - # Being a mapping is preserved by scalar multiplication. - if HasIsSingleValued( map ) then - SetIsSingleValued( ainv, IsSingleValued( map ) ); - fi; - if HasIsTotal( map ) then - SetIsTotal( ainv, IsTotal( map ) ); - fi; - - # Surjectivity and injectivity are maintained. - if HasIsInjective( map ) then - SetIsInjective( ainv, IsInjective( map ) ); - fi; - if HasIsSurjective( map ) then - SetIsSurjective( ainv, IsSurjective( map ) ); - fi; - - return ainv; - end ); - - -############################################################################# -## -#T \<( , ) -## -## method for two linear mappings from Gaussian spaces, use canonical bases? -## - - -############################################################################# -## -#M CompositionMapping2( , map1> ) for left mod. hom. & lin. g.m.b.i. -## -InstallMethod( CompositionMapping2, - "for left module hom. and linear g.m.b.i.", - FamSource1EqFamRange2, - [ IsLeftModuleHomomorphism, - IsLeftModuleGeneralMapping - and IsLinearGeneralMappingByImagesDefaultRep ], - function( map2, map1 ) - local comp, # composition of and , result - mapi1, - gens, - genimages; - - # Check that the linear mappings can be composed. - - mapi1:=MappingGeneratorsImages(map1); - # Compute images for the generators of `map1'. - if IsLinearGeneralMappingByImagesDefaultRep( map2 ) - and mapi1[2] = MappingGeneratorsImages(map2)[1] then - - gens := mapi1[1]; - genimages := MappingGeneratorsImages(map2)[2]; - - else - - gens:= mapi1[1]; - genimages:= List( mapi1[2], - v -> ImagesRepresentative( map2, v ) ); - - fi; - - # Construct the linear general mapping. - comp:= LeftModuleGeneralMappingByImages( - Source( map1 ), Range( map2 ), gens, genimages ); - - # Maintain images info (only if `gens' is not a basis). - if IsLinearGeneralMappingByImagesDefaultRep( comp ) - and not IsBound( comp!.basispreimage ) - and IsBound( map1!.basispreimage ) then - comp!.basispreimage := map1!.basispreimage; - comp!.corelations := map1!.corelations; - comp!.imagesbasispreimage := Immutable( - List( map1!.imagesbasispreimage, - v -> ImagesRepresentative( map2, v ) ) ); - fi; - - # Return the composition. - return comp; - end ); - - -############################################################################# -## -#M \+( , map2> ) . . . . . . . . . . . . . . . for two linear g.m.b.i. -## -## If both general mappings respect zero, additive inverses, scalar -## multiplication then the sum also does. -## -InstallOtherMethod( \+, - "for linear g.m.b.i. and general mapping", - IsIdenticalObj, - [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, - IsGeneralMapping ], - function( map1, map2 ) - local gens, - genimages, - mapi1, - sum; - - # Check that the linear mappings can be added. - if Source( map1 ) <> Source( map2 ) - or Range( map1 ) <> Range( map2 ) then - Error( " and must have same source and range" ); - elif PreImagesRange( map1 ) <> PreImagesRange( map2 ) then - Error( " and must have same preimage" ); - fi; - - mapi1:=MappingGeneratorsImages(map1); - - if IsLinearGeneralMappingByImagesDefaultRep( map2 ) - and mapi1[1] = MappingGeneratorsImages(map2)[1] then - - # If the generators in both general mappings are the same, - # it suffices to add the images. - gens := mapi1[1]; - genimages := mapi1[2] + MappingGeneratorsImages(map2)[2]; - - else - - # Compute images of the generators of `map1' under `map2'. - # (Note that both general mappings must be described in terms of - # `generators' in order to keep the meaning of `corelations'.) - gens:= mapi1[1]; - genimages:= mapi1[2] - + List( mapi1[1], - v -> ImagesRepresentative( map2, v ) ); - - fi; - - # Construct the linear general mapping. - sum:= LeftModuleGeneralMappingByImages( - Source( map1 ), Range( map1 ), gens, genimages ); - - # Maintain images info (only if `gens' is not a basis). - if IsLinearGeneralMappingByImagesDefaultRep( sum ) - and IsLinearGeneralMappingByImagesDefaultRep( map2 ) - and not IsBound( sum!.basispreimage ) - and IsBound( map1!.basispreimage ) - and IsBound( map2!.basispreimage ) - and map1!.basispreimage = map2!.basispreimage then - sum!.basispreimage := map1!.basispreimage; - sum!.corelations := map1!.corelations; - sum!.imagesbasispreimage := - map1!.imagesbasispreimage + map2!.imagesbasispreimage; - fi; - - # Return the sum. - return sum; -end ); - -InstallOtherMethod( \+, - "for general mapping and linear g.m.b.i.", - IsIdenticalObj, - [ IsGeneralMapping, - IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( map1, map2 ) - local gens, - genimages, - mapi2, - sum; - - # Check that the linear mappings can be added. - if Source( map1 ) <> Source( map2 ) - or Range( map1 ) <> Range( map2 ) then - Error( " and must have same source and range" ); - elif PreImagesRange( map1 ) <> PreImagesRange( map2 ) then - Error( " and must have same preimage" ); - fi; - - mapi2:=MappingGeneratorsImages(map2); - - if IsLinearGeneralMappingByImagesDefaultRep( map1 ) - and MappingGeneratorsImages(map1)[1]= mapi2[1] then - - # If the generators in both general mappings are the same, - # it suffices to add the images. - gens := mapi2[1]; - genimages := MappingGeneratorsImages(map1)[2] + mapi2[2]; - - else - - # Compute images of the generators of `map1' under `map2'. - # (Note that both general mappings must be described in terms of - # `generators' in order to keep the meaning of `corelations'.) - gens:= mapi2[1]; - genimages:= List( mapi2[1], - v -> ImagesRepresentative( map1, v ) ) - + mapi2[2]; - - fi; - - # Construct the linear general mapping. - sum:= LeftModuleGeneralMappingByImages( - Source( map1 ), Range( map1 ), gens, genimages ); - - # Maintain images info (only if `gens' is not a basis). - if IsLinearGeneralMappingByImagesDefaultRep( sum ) - and IsLinearGeneralMappingByImagesDefaultRep( map1 ) - and not IsBound( sum!.basispreimage ) - and IsBound( map1!.basispreimage ) - and IsBound( map2!.basispreimage ) - and map1!.basispreimage = map2!.basispreimage then - sum!.basispreimage := map1!.basispreimage; - sum!.corelations := map1!.corelations; - sum!.imagesbasispreimage := - map1!.imagesbasispreimage + map2!.imagesbasispreimage; - fi; - - # Return the sum. - return sum; -end ); - - -############################################################################# -## -#M \+( , ) . . . . . . . . . for two linear mappings by images -## -## The method for (total and single-valued general) mappings takes -## advantage from the fact that `generators' and `basispreimage' components -## need not be distinguished since the `corelations' component is empty. -## -InstallOtherMethod( \+, - "for linear m.b.i. and mapping", - IsIdenticalObj, - [ IsMapping and IsLinearGeneralMappingByImagesDefaultRep, - IsMapping ], - function( map1, map2 ) - local gens, - genimages, - mapi1, - sum; - - # Check that the linear mappings can be added. - if Source( map1 ) <> Source( map2 ) - or Range( map1 ) <> Range( map2 ) then - Error( " and must have same source and range" ); - elif PreImagesRange( map1 ) <> PreImagesRange( map2 ) then - Error( " and must have same preimage" ); - fi; - - if IsBound( map1!.basispreimage ) then - - # Use the basis in the construction. - gens:= map1!.basispreimage; - - if IsLinearGeneralMappingByImagesDefaultRep( map2 ) - and IsBound( map2!.basispreimage ) - and map1!.basispreimage = map2!.basispreimage then - - genimages := map1!.imagesbasispreimage + map2!.imagesbasispreimage; - - else - - genimages:= map1!.imagesbasispreimage - + List( gens, - v -> ImagesRepresentative( map2, v ) ); - - fi; - - else - - mapi1:=MappingGeneratorsImages(map1); - - if IsLinearGeneralMappingByImagesDefaultRep( map2 ) - and mapi1[1] = MappingGeneratorsImages(map2)[1] then - - # If the generators in both general mappings are the same, - # it suffices to add the images. - gens := mapi1[1]; - genimages := mapi1[2] + MappingGeneratorsImages(map2)[2]; - - else - - # Compute images of the generators of `map1' under `map2'. - # (Note that both general mappings must be described in terms of - # `generators' in order to keep the meaning of `corelations'.) - gens:= mapi1[1]; - genimages:= mapi1[2] - + List( mapi1[1], - v -> ImagesRepresentative( map2, v ) ); - - fi; - fi; - - # Construct the linear mapping. - sum:= LeftModuleHomomorphismByImagesNC( - Source( map1 ), Range( map1 ), gens, genimages ); - - # Return the sum. - return sum; - end ); - -InstallOtherMethod( \+, - "for mapping and linear m.b.i.", - IsIdenticalObj, - [ IsMapping, - IsMapping and IsLinearGeneralMappingByImagesDefaultRep ], - function( map1, map2 ) - local gens, - genimages, - mapi2, - sum; - - # Check that the linear mappings can be added. - if Source( map1 ) <> Source( map2 ) - or Range( map1 ) <> Range( map2 ) then - Error( " and must have same source and range" ); - elif PreImagesRange( map1 ) <> PreImagesRange( map2 ) then - Error( " and must have same preimage" ); - fi; - - if IsBound( map2!.basispreimage ) then - - # Use the basis in the construction. - gens:= map2!.basispreimage; - - if IsLinearGeneralMappingByImagesDefaultRep( map1 ) - and IsBound( map1!.basispreimage ) - and map1!.basispreimage = map2!.basispreimage then - - genimages := map1!.imagesbasispreimage + map2!.imagesbasispreimage; - - else - - genimages:= List( gens, v -> ImagesRepresentative( map1, v ) ) - + map2!.imagesbasispreimage; - - fi; - - else - - mapi2:=MappingGeneratorsImages(map2); - - if IsLinearGeneralMappingByImagesDefaultRep( map1 ) - and MappingGeneratorsImages(map1)[1] = mapi2[1] then - - # If the generators in both general mappings are the same, - # it suffices to add the images. - gens := mapi2[1]; - genimages := MappingGeneratorsImages(map1)[2] + mapi2[2]; - - else - - # Compute images of the generators of `map2' under `map1'. - # (Note that both general mappings must be described in terms of - # `generators' in order to keep the meaning of `corelations'.) - gens:= mapi2[1]; - genimages:= List( mapi2[1], - v -> ImagesRepresentative( map1, v ) ) - + mapi2[2]; - - fi; - - fi; - - # Construct the linear mapping. - sum:= LeftModuleHomomorphismByImagesNC( - Source( map1 ), Range( map1 ), gens, genimages ); - - # Return the sum. - return sum; - end ); - - -############################################################################# -## -## 2. methods for linear mappings given by matrices -## - - -############################################################################# -## -#R IsLinearMappingByMatrixDefaultRep -## -## is another default representation of $F$-linear mappings between -## two free left modules $V$ and $W$ where $F$ is equal to the left acting -## domain of $V$ and of $W$. -## -## Defining components are -## -## `basissource' \: \\ -## basis of $V$, -## -## `basisrange' \: \\ -## basis of $W$, -## -## `matrix' \: \\ -## matrix over $F$, of dimensions $\dim(V)$ times $\dim(W)$. -## -## The mapping is defined as follows. -## The image of a vector in $V$ has coefficients -## `Coefficients( !.basissource ) * !.matrix' -## w.r.t. `!.basisrange'. -## -## If one wants to compute preimages, one needs the components -## `basisimage' \: \\ -## basis of the image of , -## -## `preimagesbasisimage' \: \\ -## preimages of the basis vectors of `basisimage', -## -## `relations' \: \\ -## linearly independent generators for the relation space, -## i.e., of the left null space of `!.matrix'. -## (The corresponding linear combinations of `basissource' -## generate the kernel.) -## -## If these components are not yet bound, they are computed by -## `MakePreImagesInfoLinearMappingByMatrix'. -## -## Computed images and preimages of free left modules under linear mappings -## are always free left modules. -## If one needs more structure (e.g., that of an algebra) for an image or -## preimage then the linear mapping must have a special representation. -## -## Note that the inverse general mapping of a linear mapping defined by -## a matrix is best handled if it uses the default method, -## since such an inverse general mapping delegates the tasks of computing -## (pre)images to the original general mapping. -## So the (pre)images info is computed only once. -#T but what about sums of such mappings? -#T better try to share info also in this case? -#T (share a list that is filled with the info later?) -## -DeclareRepresentation( - "IsLinearMappingByMatrixDefaultRep", - IsAttributeStoringRep, - [ "basissource", "basisrange", "matrix", - "basisimage", "preimagesbasisimage", "relations" ] ); - -InstallTrueMethod( IsAdditiveElementWithInverse, - IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ); -InstallTrueMethod( IsLeftModuleGeneralMapping, - IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ); - - -############################################################################# -## -#M LeftModuleHomomorphismByMatrix( , ,
) -## -## is the total and single-valued linear general mapping with a basis -## of the source and
a basis of the range, and the rows of the matrix -## being the coefficients vectors of the images of w.r.t. -##
. -## -InstallMethod( LeftModuleHomomorphismByMatrix, - "for two bases of free left modules and a matrix", - [ IsBasis, IsMatrix, IsBasis ], - function( BS, matrix, BR ) - local S, R, map; - - S:= UnderlyingLeftModule( BS ); - R:= UnderlyingLeftModule( BR ); - - # Check the arguments. - if Length( BS ) <> Length( matrix ) then - Error( " and must have the same length" ); - elif Length( BR ) <> Length( matrix[1] ) then - Error( "
and [1] must have the same length" ); - elif LeftActingDomain( S ) <> LeftActingDomain( R ) then - Error( " and must have same left acting domain" ); - fi; -#T check entries of the matrix? - - # Make the mapping. - map:= Objectify( TypeOfDefaultGeneralMapping( S, R, - IsSPGeneralMapping - and IsSingleValued - and IsTotal - and IsLeftModuleGeneralMapping - and IsLinearMappingByMatrixDefaultRep ), - rec( - basissource := BS, - matrix := Immutable( matrix ), - basisrange := BR - ) ); - - # return the mapping - return map; - end ); - - -############################################################################# -## -#F MakePreImagesInfoLinearMappingByMatrix( ) -## -## Provide the information for computing preimages, that is, set up -## the components `basisimage', `preimagesbasisimage', `relations'. -## -BindGlobal( "MakePreImagesInfoLinearMappingByMatrix", function( map ) - local ech, - B; - - ech:= SemiEchelonMatTransformation( map!.matrix ); - B:= Basis( Range( map ) ); - map!.basisimage := BasisNC( ImagesSource( map ), - List( ech.vectors, - x -> LinearCombination( B, x ) ) ); - map!.relations := Immutable( ech.relations ); - - map!.preimagesbasisimage := Immutable( List( ech.coeffs, - row -> LinearCombination( - map!.basissource, row ) ) ); -end ); - - -############################################################################# -## -#M KernelOfAdditiveGeneralMapping( ) . . . . . for left module m.b.m. -## -InstallMethod( KernelOfAdditiveGeneralMapping, - "for left module m.b.m.", - [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], - function( map ) - local generators, S; - - # Form the linear combinations of the basis vectors for the - # relation space with the `basissource' of `map'. - - if not IsBound( map!.relations ) then - MakePreImagesInfoLinearMappingByMatrix( map ); - fi; - generators:= BasisVectors( map!.basissource ); - S:= Source( map ); - return LeftModuleByGenerators( LeftActingDomain( S ), - List( map!.relations, - r -> LinearCombination( generators, r ) ), - Zero( S ) ); - end ); - - -############################################################################# -## -#M IsInjective( ) . . . . . . . . . . . . . . for left module m.b.m. -## -InstallMethod( IsInjective, - "for left module m.b.m.", - [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], - function( map ) - local generators; - - if not IsBound( map!.relations ) then - MakePreImagesInfoLinearMappingByMatrix( map ); - fi; - generators:= BasisVectors( map!.basissource ); - return ForAll( map!.relations, - r -> IsZero( LinearCombination( generators, r ) ) ); - end ); - - -############################################################################# -## -#M ImagesRepresentative( , ) . . . . . . for left module m.b.m. -## -InstallMethod( ImagesRepresentative, - "for left module m.b.m., and element", - FamSourceEqFamElm, - [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, - IsObject ], - function( map, elm ) - elm:= Coefficients( map!.basissource, elm ); - if elm <> fail then - elm:= LinearCombination( map!.basisrange, elm * map!.matrix ); - fi; - return elm; - end ); - - -############################################################################# -## -#M PreImagesRepresentativeNC( , ) . . . . for left module m.b.m. -## -InstallMethod( PreImagesRepresentativeNC, - "for left module m.b.m., and element", - FamRangeEqFamElm, - [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, - IsObject ], - function( map, elm ) - if not IsBound( map!.basisimage ) then - MakePreImagesInfoLinearMappingByMatrix( map ); - fi; - elm:= Coefficients( map!.basisimage, elm ); - if elm = fail then - return fail; - fi; - return LinearCombination( map!.preimagesbasisimage, elm ); - end ); - -InstallMethod( PreImagesRepresentative, - "for left module m.b.m., and element", - FamRangeEqFamElm, - [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, - IsObject ], - function( map, elm ) - if not ( elm in Image( map ) ) then - return fail; - fi; - return PreImagesRepresentativeNC( map, elm ); - end ); - - -############################################################################# -## -#M ViewObj( ) . . . . . . . . . . . . . . . . for left module m.b.m. -## -InstallMethod( ViewObj, - "for a left module m.b.m.", - [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], - function( map ) - Print( " " ); - View( UnderlyingLeftModule( map!.basisrange ) ); - Print( ">" ); - end ); - - -############################################################################# -## -#M PrintObj( ) . . . . . . . . . . . . . . . . for left module m.b.m. -## -InstallMethod( PrintObj, - "for a left module m.b.m.", - [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], - function( map ) - Print( "LeftModuleHomomorphismByMatrix( ", - map!.basissource, ", ", map!.matrix, ", ", - map!.basisrange, " )" ); - end ); - - -############################################################################# -## -#M NaturalHomomorphismBySubspace( , ) . . . for free left modules -## -## Return the identity mapping. -## -InstallMethod( NaturalHomomorphismBySubspace, - "for left module and trivial left module", - IsIdenticalObj, - [ IsFreeLeftModule, IsFreeLeftModule and IsTrivial ], - SUM_FLAGS, # better than everything else - function( V, W ) - return IdentityMapping( V ); - end ); - - -############################################################################# -## -#F NaturalHomomorphismBySubspaceOntoFullRowSpace( , ) -## -InstallGlobalFunction( NaturalHomomorphismBySubspaceOntoFullRowSpace, - function( V, W ) - local F, - Wvectors, - mb, - compl, - gen, - B, - img, - canbas, - zero, - Bimgs, - nathom; - - # Check that the modules are finite dimensional. - if not IsFiniteDimensional( V ) or not IsFiniteDimensional( W ) then - TryNextMethod(); - elif not IsSubset( V, W ) then - Error( " must be contained in " ); - fi; - - # If the left acting domains are different, adjust them. - F:= LeftActingDomain( V ); - if F <> LeftActingDomain( W ) then - F:= Intersection2( F, LeftActingDomain( W ) ); - V:= AsLeftModule( F, V ); - W:= AsLeftModule( F, W ); - fi; - - # If `V' is equal to `W', return a zero mapping. - if Dimension( V ) = Dimension( W ) then - return ZeroMapping( V, FullRowModule( F, 0 ) ); - fi; - - # Compute a basis of `V' through a basis of `W'. - Wvectors:= BasisVectors( Basis( W ) ); - if IsEmpty( Wvectors ) then - mb:= MutableBasis( F, Wvectors, Zero( W ) ); - else - mb:= MutableBasis( F, Wvectors ); - fi; - compl:= []; - for gen in BasisVectors( Basis( V ) ) do - if CloseMutableBasis( mb, gen ) then - Add( compl, gen ); - fi; - od; - B:= BasisNC( V, Concatenation( Wvectors, compl ) ); - - # Compute the linear mapping by images. - img:= FullRowModule( F, Length( compl ) ); - canbas:= CanonicalBasis( img ); - zero:= Zero( img ); - Bimgs:= Concatenation( List( Wvectors, v -> zero ), - BasisVectors( canbas ) ); - nathom:= LeftModuleHomomorphismByMatrix( B, Bimgs, canbas ); -#T take a special representation for nat. hom.s, -#T (just compute coefficients, and then choose a subset ...) - SetIsSurjective( nathom, true ); - - # Enter the preimages info. - nathom!.basisimage:= canbas; - nathom!.preimagesbasisimage:= Immutable( compl ); -#T relations are not needed if the kernel is known ? - - SetKernelOfAdditiveGeneralMapping( nathom, W ); - - # Run the implications for the factor. - UseFactorRelation( V, W, img ); - - return nathom; - end ); - - -############################################################################# -## -#M NaturalHomomorphismBySubspace( , ) . . . for two free left modules -## -## return a left module m.b.m. -## -InstallMethod( NaturalHomomorphismBySubspace, - "for two finite dimensional free left modules", - IsIdenticalObj, - [ IsFreeLeftModule, IsFreeLeftModule ], - NaturalHomomorphismBySubspaceOntoFullRowSpace ); - - -############################################################################# -## -#M \*( , ) . . . . . . . . . . . . . for scalar and linear m.b.m. -## -InstallMethod( \*, - "for scalar and linear m.b.m.", - [ IsMultiplicativeElement, - IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], - function( scalar, map ) - local mult, # the multiple of `map', result - F; # left acting domain - - # Check the scalar. - # (Maybe it is in fact another mapping, and we want to compose.) - if not IsInt( scalar ) - and not IsElmsColls( FamilyObj( scalar ), - FamilyObj( LeftActingDomain( Range( map ) ) ) ) then - TryNextMethod(); - fi; - - # Construct the linear mapping (if possible). - mult:= LeftModuleHomomorphismByMatrix( - map!.basissource, - scalar * map!.matrix, - map!.basisrange ); - - # If the scalar is invertible in the left acting domain of the source - # then surjectivity and injectivity are maintained as well as the image. - F:= LeftActingDomain( Source( map ) ); - if scalar in F and IsUnit( F, scalar ) then - - if HasIsInjective( map ) then - SetIsInjective( mult, IsInjective( map ) ); - fi; - if HasIsSurjective( map ) then - SetIsSurjective( mult, IsSurjective( map ) ); - fi; - - if IsBound( map!.basisimage ) then - scalar:= Inverse( scalar ); - mult!.basisimage := map!.basisimage; - mult!.preimagesbasisimage := Immutable( - List( map!.preimagesbasisimage, v -> scalar * v ) ); - mult!.relations := map!.relations; - fi; - - fi; - - return mult; - end ); - - -############################################################################# -## -#M AdditiveInverseOp( ) . . . . . . . . . . . . . . for linear m.b.m. -## -InstallMethod( AdditiveInverseOp, - "for linear m.b.m.", - [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], - function( map ) - local ainv; # the additive inverse of `map', result - - # Construct the linear general mapping (if possible). - ainv:= LeftModuleHomomorphismByMatrix( - map!.basissource, - AdditiveInverse( map!.matrix ), - map!.basisrange ); - - # Maintain preimages info. - if IsBound( map!.basisimage ) then - ainv!.basisimage := map!.basisimage; - ainv!.preimagesbasisimage := Immutable( - List( map!.preimagesbasisimage, AdditiveInverse ) ); - ainv!.relations := map!.relations; - fi; - - # Surjectivity and injectivity are maintained. - if HasIsInjective( map ) then - SetIsInjective( ainv, IsInjective( map ) ); - fi; - if HasIsSurjective( map ) then - SetIsSurjective( ainv, IsSurjective( map ) ); - fi; - - return ainv; - end ); - - -############################################################################# -## -#M CompositionMapping2( , map1> ) . for left mod. hom. & lin. m.b.m. -## -InstallMethod( CompositionMapping2, - "for left module hom. and linear m.b.m.", - FamSource1EqFamRange2, - [ IsLeftModuleHomomorphism, - IsLeftModuleHomomorphism and IsLinearMappingByMatrixDefaultRep ], - function( map2, map1 ) - local comp, # composition of and , result - BR, # basis of the range of `map2' - mat2; # matrix corresponding to `map2' - - # Compute images for the generators of `map1'. - if IsLinearMappingByMatrixDefaultRep( map2 ) - and map1!.basisrange = map2!.basissource then - - BR := map2!.basisrange; - mat2 := map2!.matrix; - - else - - BR:= Range( map2 ); - if not IsFiniteDimensional( BR ) then - TryNextMethod(); - fi; - BR:= Basis( BR ); - mat2:= List( BasisVectors( map1!.basisrange ), - v -> Coefficients( BR, ImagesRepresentative( map2, v ) ) ); - - fi; - - # Construct the linear mapping. - comp:= LeftModuleHomomorphismByMatrix( map1!.basissource, - map1!.matrix * mat2, BR ); - - # Return the composition. - return comp; - end ); - - -############################################################################# -## -#M \+( , map2> ) . . . . . . . . . . . . . . . . for two linear m.b.m. -## -## Two general mappings that respect addition can be added pointwise -## if their images are equal and their preimages are equal. -## The sum does also respect addition. -## -## If both general mappings respect zero, additive inverses, scalar -## multiplication then the sum also does. -## -BindGlobal( "SumOfMBMAndMapping", function( map1, map2 ) - local sum; - - # Check that the linear mappings can be added. - if Source( map1 ) <> Source( map2 ) - or Range( map1 ) <> Range( map2 ) then - Error( " and must have same source and range" ); - fi; - - if IsLinearMappingByMatrixDefaultRep( map2 ) - and map1!.basissource = map2!.basissource - and map1!.basisrange = map2!.basisrange then - - # If the bases in both mappings are the same, - # it suffices to add the matrices. - sum:= LeftModuleHomomorphismByMatrix( - map1!.basissource, - map1!.matrix + map2!.matrix, - map1!.basisrange ); - - else - - # Compute images of the generators of `map1' under `map2'. - sum:= LeftModuleHomomorphismByMatrix( - map1!.basissource, - map1!.matrix - + List( BasisVectors( map1!.basissource ), - v -> Coefficients( map1!.basisrange, - ImagesRepresentative( map2, v ) ) ), - map1!.basisrange ); - - fi; - - # Return the sum. - return sum; -end ); - -BindGlobal( "SumOfMappingAndMBM", function( map1, map2 ) - local sum; - - # Check that the linear mappings can be added. - if Source( map1 ) <> Source( map2 ) - or Range( map1 ) <> Range( map2 ) then - Error( " and must have same source and range" ); - fi; - - if IsLinearMappingByMatrixDefaultRep( map1 ) - and map1!.basissource = map2!.basissource - and map1!.basisrange = map2!.basisrange then - - # If the bases in both mappings are the same, - # it suffices to add the matrices. - sum:= LeftModuleHomomorphismByMatrix( - map1!.basissource, - map1!.matrix + map2!.matrix, - map1!.basisrange ); - - else - - # Compute images of the generators of `map2' under `map1'. - sum:= LeftModuleHomomorphismByMatrix( - map2!.basissource, - List( BasisVectors( map2!.basissource ), - v -> Coefficients( map2!.basisrange, - ImagesRepresentative( map1, v ) ) ) - + map2!.matrix, - map2!.basisrange ); - - fi; - - # Return the sum. - return sum; -end ); - -InstallOtherMethod( \+, - "for linear m.b.m. and mapping", - IsIdenticalObj, - [ IsMapping and IsLinearMappingByMatrixDefaultRep, - IsMapping ], - SumOfMBMAndMapping ); - -InstallOtherMethod( \+, - "for mapping and linear m.b.m.", - IsIdenticalObj, - [ IsMapping, - IsMapping and IsLinearMappingByMatrixDefaultRep ], - SumOfMappingAndMBM ); - - -############################################################################# -## -#M \+( , ) . . . . for mapping by matrix and mapping by images -## -InstallMethod( \+, - "for linear m.b.m. and linear m.b.i.", - IsIdenticalObj, - [ IsMapping and IsLinearMappingByMatrixDefaultRep, - IsMapping and IsLinearGeneralMappingByImagesDefaultRep ], - SumOfMBMAndMapping ); - -InstallMethod( \+, - "for linear m.b.i. and linear m.b.m.", - IsIdenticalObj, - [ IsMapping and IsLinearGeneralMappingByImagesDefaultRep, - IsMapping and IsLinearMappingByMatrixDefaultRep ], - SumOfMappingAndMBM ); - - -############################################################################# -## -## 3. methods for vector spaces of linear mappings -## - - -############################################################################# -## -#M NiceFreeLeftModuleInfo( ) . . . . . . for a space of linear mappings -#M NiceVector( , ) . . for space of lin. mappings, and lin. mapping -#M UglyVector( , ) . . . for space of linear mappings, and matrix -## -InstallHandlingByNiceBasis( "IsLinearMappingsModule", rec( - detect := function( F, gens, V, zero ) - local S, R; - if not IsGeneralMappingCollection( V ) then - return false; - fi; - gens:= AsList( gens ); - if IsEmpty( gens ) then - S:= Source( zero ); - R:= Range( zero ); - else - S:= Source( gens[1] ); - R:= Range( gens[1] ); - fi; - - # Check that the mappings have left modules as source and range. - if not IsLeftModule( S ) - or not IsLeftModule( R ) - or not ForAll( gens, IsMapping ) then - return false; - fi; - - # Check that all generators have the same source and range, - # and that source and range are in fact left modules. - if ForAny( gens, map -> Source( map ) <> S ) - or ForAny( gens, map -> Range( map ) <> R ) then - return false; - fi; - return true; - end, - - NiceFreeLeftModuleInfo := function( V ) - local F, z, S, R; - F:= LeftActingDomain( V ); - z:= Zero( V ); - S:= Source( z ); - R:= Range( z ); - - # Write `S' and `R' over `F' (necessary for the nice left module). - if LeftActingDomain( S ) <> F then - S:= AsLeftModule( F, S ); - R:= AsLeftModule( F, R ); - fi; - - return rec( basissource := Basis( S ), - basisrange := Basis( R ) ); - end, - - NiceVector := function( V, v ) - local info, M, i, c; - info:= NiceFreeLeftModuleInfo( V ); - if IsLinearMappingByMatrixDefaultRep( v ) - and info.basissource = v!.basissource - and info.basisrange = v!.basisrange then - M:= v!.matrix; - else - M:= []; - for i in BasisVectors( info.basissource ) do - c:= Coefficients( info.basisrange, ImagesRepresentative( v, i ) ); - if c = fail then - return fail; - fi; - Add( M, c ); - od; - fi; - return M; - end, - - UglyVector := function( V, mat ) - local info; - info:= NiceFreeLeftModuleInfo( V ); - return LeftModuleHomomorphismByMatrix( info.basissource, - mat, info.basisrange ); - end ) ); - - -############################################################################# -## -## 4. methods for algebras of linear mappings -## - - -############################################################################# -## -#M RingByGenerators( ) . . ring generated by a list of lin. mappings -## -## If is a list of linear mappings of finite vector spaces then -## we construct a hom algebra over the prime field. -## -InstallOtherMethod( RingByGenerators, - "for a list of linear mappings of finite vector spaces", - [ IsGeneralMappingCollection ], - function( maps ) - local S; - - maps:= AsList( maps ); - if IsEmpty( maps ) then - Error( "need at least one element" ); - fi; - if not ForAll( maps, IsLeftModuleHomomorphism ) then - TryNextMethod(); - fi; - S:= Source( maps[1] ); - if IsVectorSpace( S ) - and IsFFECollection( LeftActingDomain( S ) ) then - return FLMLORByGenerators( GF( Characteristic( S ) ), maps ); - elif IsVectorSpace( S ) - and IsCyclotomicCollection( LeftActingDomain( S ) ) then - return FLMLORByGenerators( Integers, maps ); - else - TryNextMethod(); - fi; - end ); - - -############################################################################# -## -#M DefaultRingByGenerators( ) . . ring cont. a list of lin. mappings -## -## If is a list of mappings of vector spaces then -## we construct an algebra over the prime field. -## (So this may differ from the result of `RingByGenerators' if the -## characteristic is zero.) -## -InstallOtherMethod( DefaultRingByGenerators, - "for a list of linear mappings of vector spaces", - [ IsGeneralMappingCollection ], - function( maps ) - local S; - maps:= AsList( maps ); - if IsEmpty( maps ) then - Error( "need at least one element" ); - fi; - if not ForAll( maps, IsLeftModuleHomomorphism ) then - TryNextMethod(); - fi; - S:= Source( maps[1] ); - if IsVectorSpace( S ) - and IsFFECollection( LeftActingDomain( S ) ) then - return FLMLORByGenerators( GF( Characteristic( S ) ), maps ); - elif IsVectorSpace( S ) - and IsCyclotomicCollection( LeftActingDomain( S ) ) then - return FLMLORByGenerators( Rationals, maps ); - else - TryNextMethod(); - fi; - end ); - - -############################################################################# -## -#M RingWithOneByGenerators( ) . . . . . for a list of linear mappings -## -## If is a list of linear mappings of a finite vector space then -## we construct a hom algebra-with-one over the prime field. -## -InstallOtherMethod( RingWithOneByGenerators, - "for a list of linear mappings of finite vector spaces", - [ IsGeneralMappingCollection ], - function( maps ) - local S; - - maps:= AsList( maps ); - if IsEmpty( maps ) then - Error( "need at least one element" ); - fi; - if not ForAll( maps, IsLeftModuleHomomorphism ) then - TryNextMethod(); - fi; - S:= Source( maps[1] ); - if IsVectorSpace( S ) - and IsFFECollection( LeftActingDomain( S ) ) - and S = Range( maps[1] ) then - return FLMLORWithOneByGenerators( GF( Characteristic( S ) ), maps ); - elif IsVectorSpace( S ) - and IsCyclotomicCollection( LeftActingDomain( S ) ) then - return FLMLORWithOneByGenerators( Integers, maps ); - else - TryNextMethod(); - fi; - end ); - - -############################################################################# -## -#M IsGeneratorsOfFLMLOR( , ) -#M IsGeneratorsOfFLMLORWithOne( , ) -## -#T check that sources and ranges coincide: -#T if ForAny( maps, map -> Source( map ) <> S or Range( map ) <> S ) then - -#T add implication that a FLMLOR of mappings is associative! - -#T for ideals construction, inherit the info? -#T SetNiceFreeLeftModuleInfo( I, NiceFreeLeftModuleInfo( A ) ); - - -############################################################################# -## -## 5. methods for full hom spaces -## - - -############################################################################# -## -#M IsFullHomModule( V ) . . . . . . . . . . . for space of linear mappings -## -InstallMethod( IsFullHomModule, - "for space of linear mappings", - [ IsFreeLeftModule and IsGeneralMappingCollection ], - V -> Dimension( V ) = Dimension( UnderlyingLeftModule( NiceFreeLeftModuleInfo( V ).basissource ) ) - * Dimension( UnderlyingLeftModule( NiceFreeLeftModuleInfo( V ).basisrange ) ) ); - - -############################################################################# -## -#M Dimension( ) . . . . . . . . . for full hom space of linear mappings -## -InstallMethod( Dimension, - "for full hom space of linear mappings", - [ IsFreeLeftModule and IsGeneralMappingCollection - and IsFullHomModule ], - V -> Dimension( UnderlyingLeftModule( NiceFreeLeftModuleInfo( V ).basissource ) ) - * Dimension( UnderlyingLeftModule( NiceFreeLeftModuleInfo( V ).basisrange ) ) ); - - -############################################################################# -## -#M Random( ) . . . . . . . . . . . for full hom space of linear mappings -## -InstallMethodWithRandomSource( Random, - "for a random source and full hom space of linear mappings", - [ IsRandomSource, IsFreeLeftModule and IsGeneralMappingCollection - and IsFullHomModule ], - function( rs, M ) - local BS, BR; - - BR:= NiceFreeLeftModuleInfo( M ); - BS:= BR.basissource; - BR:= BR.basisrange; - - return LeftModuleHomomorphismByMatrix( BS, - RandomMat( rs, - Dimension( UnderlyingLeftModule( BS ) ), - Dimension( UnderlyingLeftModule( BR ) ), - LeftActingDomain( M ) ), - BR ); - end ); - - -############################################################################# -## -#M Representative( ) . . . . . . . for full hom space of linear mappings -## -## This method is necessary for example for computing the `Zero' value of -## . Note that does in general *not* store any generators! -## -InstallMethod( Representative, - "for full hom space of linear mappings", - [ IsFreeLeftModule and IsGeneralMappingCollection - and IsFullHomModule ], - function( M ) - local BS, BR; - - BR:= NiceFreeLeftModuleInfo( M ); - BS:= BR.basissource; - BR:= BR.basisrange; - - return LeftModuleHomomorphismByMatrix( BS, - NullMat( Dimension( UnderlyingLeftModule( BS ) ), - Dimension( UnderlyingLeftModule( BR ) ), - LeftActingDomain( M ) ), - BR ); - end ); - - -############################################################################# -## -#M GeneratorsOfLeftModule( ) . . . for full hom space of linear mappings -## -BindGlobal( "StandardGeneratorsOfFullHomModule", function( M ) - local BS, BR, R, one, m, n, zeromat, gens, i, j, gen; - - BR:= NiceFreeLeftModuleInfo( M ); - BS:= BR.basissource; - BR:= BR.basisrange; - R:= LeftActingDomain( M ); - one:= One( R ); - m:= Dimension( UnderlyingLeftModule( BS ) ); - n:= Dimension( UnderlyingLeftModule( BR ) ); - zeromat:= NullMat( m, n, R ); - gens:= []; - for i in [ 1 .. m ] do - for j in [ 1 .. n ] do - gen:= List( zeromat, ShallowCopy ); - gen[i][j]:= one; - Add( gens, LeftModuleHomomorphismByMatrix( BS, gen, BR ) ); - od; - od; - - return gens; -end ); - -InstallMethod( GeneratorsOfLeftModule, - "for full hom space of linear mappings", - [ IsFreeLeftModule and IsGeneralMappingCollection - and IsFullHomModule ], - StandardGeneratorsOfFullHomModule ); - - -############################################################################# -## -#M NiceFreeLeftModule( ) . . . . . for full hom space of linear mappings -## -## We need a special method since we decided not to store vector space -## generators in full hom spaces; -## note that the default methods for `NiceFreeLeftModule' are installed with -## requirement `HasGeneratorsOfLeftModule'. -## -InstallMethod( NiceFreeLeftModule, - "for full hom space of linear mappings", - [ IsFreeLeftModule and IsGeneralMappingCollection - and IsFullHomModule ], - function( M ) - if HasGeneratorsOfLeftModule( M ) then - TryNextMethod(); - fi; - GeneratorsOfLeftModule( M ); - if not HasGeneratorsOfLeftModule( M ) then - TryNextMethod(); - fi; - return NiceFreeLeftModule( M ); - end ); - - -############################################################################# -## -#M ViewObj( ) . . . . . . . . . . for full hom space of linear mappings -#M PrintObj( ) . . . . . . . . . . for full hom space of linear mappings -## -BindGlobal( "ViewFullHomModule", function( M ) - local info; - - info:= NiceFreeLeftModuleInfo( M ); - if IsIdenticalObj( info.basissource, info.basisrange ) then - Print( "End( " ); - View( LeftActingDomain( M ) ); - Print( ", " ); - View( UnderlyingLeftModule( info.basissource ) ); - Print( " )" ); - else - Print( "Hom( " ); - View( LeftActingDomain( M ) ); - Print( ", " ); - View( UnderlyingLeftModule( info.basissource ) ); - Print( ", " ); - View( UnderlyingLeftModule( info.basisrange ) ); - Print( " )" ); - fi; -end ); - -InstallMethod( ViewObj, - "for full hom space of linear mappings", - [ IsFreeLeftModule and IsGeneralMappingCollection - and IsFullHomModule ], SUM_FLAGS, - ViewFullHomModule ); - -InstallMethod( PrintObj, - "for full hom space of linear mappings", - [ IsFreeLeftModule and IsGeneralMappingCollection - and IsFullHomModule ], SUM_FLAGS, - ViewFullHomModule ); - - -############################################################################# -## -#M \in( , ) . . . . . . . . . . for full hom space of linear mappings -## -InstallMethod( \in, - "for full hom space of linear mappings", - IsElmsColls, - [ IsGeneralMapping, - IsFreeLeftModule and IsGeneralMappingCollection - and IsFullHomModule ], - function( map, M ) - local info; - info:= NiceFreeLeftModuleInfo( M ); - return Source( map ) = UnderlyingLeftModule( info.basissource ) - and Range( map ) = UnderlyingLeftModule( info.basisrange ) - and IsLeftModuleHomomorphism( map ); - end ); - - -############################################################################# -## -#M IsPseudoCanonicalBasisFullHomModule( ) . . . . for a full hom module -## -InstallMethod( IsPseudoCanonicalBasisFullHomModule, - "for a basis of a full hom module", - [ IsBasis ], - function( B ) - local V; - - V:= UnderlyingLeftModule( B ); - if IsGeneralMappingCollection( V ) then - if not IsFullHomModule( V ) then - return false; - fi; - return BasisVectors( B ) = StandardGeneratorsOfFullHomModule( V ); - else - Error( "do not know what a pseudo canon. basis for is" ); - fi; - end ); - - -############################################################################# -## -#M BasisVectors( ) . . . for pseudo canonical basis of a full hom module -## -InstallMethod( BasisVectors, - "for pseudo canonical basis of a full hom module", - [ IsBasis and IsPseudoCanonicalBasisFullHomModule ], - B -> StandardGeneratorsOfFullHomModule( UnderlyingLeftModule( B ) ) ); - - -############################################################################# -## -#M Coefficients( , ) for a pseudo canon. basis of a full hom module -## -InstallOtherMethod( Coefficients, - "for pseudo canon. basis of a full hom module, and lin. mapping", - IsCollsElms, - [ IsBasis and IsPseudoCanonicalBasisFullHomModule, IsGeneralMapping ], - function( B, map ) - local V, info; - V:= UnderlyingLeftModule( B ); - if not IsGeneralMappingCollection( V ) then - TryNextMethod(); - fi; - info:= NiceFreeLeftModuleInfo( V ); - if Source( map ) = UnderlyingLeftModule( info.basissource ) - and Range( map ) = UnderlyingLeftModule( info.basisrange ) - and IsLeftModuleHomomorphism( map ) then - return Concatenation( - List( BasisVectors( info.basissource ), - v -> Coefficients( info.basisrange, - ImagesRepresentative( map, v ) ) ) ); - else - return fail; - fi; - end ); - -InstallMethod( Coefficients, - "for pseudo can. basis of full hom module, and lin. m.b.m.", - IsCollsElms, - [ IsBasis and IsPseudoCanonicalBasisFullHomModule, - IsMapping and IsLinearMappingByMatrixDefaultRep ], - function( B, map ) - local V, info; - V:= UnderlyingLeftModule( B ); - if not IsGeneralMappingCollection( V ) then - TryNextMethod(); - fi; - info:= NiceFreeLeftModuleInfo( V ); - if map!.basissource = info.basissource - and map!.basisrange = info.basisrange then - return Concatenation( map!.matrix ); - elif Source( map ) = UnderlyingLeftModule( info.basissource ) - and Range( map ) = UnderlyingLeftModule( info.basisrange ) then - return Concatenation( - List( BasisVectors( info.basissource ), - v -> Coefficients( info.basisrange, - ImagesRepresentative( map, v ) ) ) ); - else - return fail; - fi; - end ); - - -############################################################################# -## -#M Basis( ) . . . . . . . . . . . . . . . . . . . . for full hom module -## -InstallMethod( Basis, - "for full hom space of linear mappings", - [ IsFreeLeftModule and IsFullHomModule ], 100, - function( V ) - local B; - B:= Objectify( NewType( FamilyObj( V ), - IsFiniteBasisDefault - and IsPseudoCanonicalBasisFullHomModule - and IsAttributeStoringRep ), - rec() ); - SetUnderlyingLeftModule( B, V ); - if IsFiniteDimensional( V ) then - SetIsFinite( B, true ); - #T Check whether its is a) correct and even if so - #T b) sometimes to expensive - SetBasisVectors( B, GeneratorsOfLeftModule(V) ); - fi; - return B; - end ); - - -############################################################################# -## -#M Hom( , , ) -## -InstallMethod( Hom, - "for division ring and two free left modules", - [ IsDivisionRing, IsFreeLeftModule, IsFreeLeftModule ], - function( F, V, W ) - local M; # the free module record, result - - if V = W then - return End( F, V ); - fi; - if LeftActingDomain( V ) <> F then - V:= AsLeftModule( F, V ); - fi; - if LeftActingDomain( W ) <> F then - W:= AsLeftModule( F, W ); - fi; - - M:= Objectify( NewType( CollectionsFamily( GeneralMappingsFamily( - ElementsFamily( FamilyObj( V ) ), - ElementsFamily( FamilyObj( W ) ) ) ), - IsFreeLeftModule - and IsFullHomModule - and IsLinearMappingsModule - and IsGeneralMappingCollection - and IsAttributeStoringRep ), - rec() ); - - SetLeftActingDomain( M, F ); - SetNiceFreeLeftModuleInfo( M, rec( - basissource := Basis( V ), - basisrange := Basis( W ) ) ); - - return M; - end ); - - -############################################################################# -## -#M End( , ) . . . . . . . . . for division ring and free left module -## -## We use the generators that are also taken for full matrix FLMLORs. -## -InstallMethod( End, - "for division ring and space of linear mappings", - [ IsDivisionRing, IsFreeLeftModule ], - function( F, V ) - local n, # dimension of `V' - i, # loop over the rows - gens, # list of generators - one, # the identity of the field - B, # basis of `V' - A; # algebra, result - - if LeftActingDomain( V ) <> F then - V:= AsLeftModule( F, V ); - fi; - - n:= Dimension( V ); - gens:= NullMat( n, n, F ); - gens:= [ gens, List( gens, ShallowCopy ) ]; - one:= One( F ); - - # Construct the generators. - gens[1][1][1]:= one; - gens[2][1][n]:= one; - for i in [ 2 .. n ] do - gens[2][i][i-1]:= one; - od; - B:= Basis( V ); - gens:= List( gens, mat -> LeftModuleHomomorphismByMatrix( B, mat, B ) ); - - # Construct the FLMLOR. - A:= AlgebraWithOneByGenerators( F, gens ); - SetIsFullHomModule( A, true ); - SetNiceFreeLeftModuleInfo( A, rec( - basissource := B, - basisrange := B ) ); - - # Return the FLMLOR. - return A; - end ); - - -#T InstallMethod( Field, true, [ IsGeneralMappingCollection ], 0, ... ); -#T InstallMethod( DefaultField, true, [ IsGeneralMappingCollection ], 0, ... ); From 59dd0efab0378717523002d9087fd00a330f950b Mon Sep 17 00:00:00 2001 From: cdwensley Date: Mon, 6 Jul 2026 21:26:37 +0100 Subject: [PATCH 052/114] fix a ref in mapping.gd, line 980 --- lib/mapping.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapping.gd b/lib/mapping.gd index 2b391b67cb..93862917a5 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -977,7 +977,7 @@ DeclareGlobalFunction( "Images" ); ## ## ## If elm is an element of the range of the general mapping -## map then returns the set of all +## map then returns the set of all ## preimages of elm under map. ##

## From &GAP; version 4.16.0 From c6d4f4e62d4d6226fcf626c66bab1cb12b8255de Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 8 Jul 2026 20:10:32 +0100 Subject: [PATCH 053/114] made changes suggested by Thomas --- lib/alglie.gi | 2 +- lib/field.gi | 4 +-- lib/liefam.gi | 2 +- lib/mapping.gd | 29 +++++++++++----- lib/mapping.gi | 50 ++++++++++----------------- lib/mapprep.gi | 42 +++++++++++++++------- lib/mgmring.gi | 10 +++++- lib/relation.gi | 92 ++++++++++++++++++++++++++----------------------- lib/vspchom.gi | 4 +-- 9 files changed, 134 insertions(+), 101 deletions(-) diff --git a/lib/alglie.gi b/lib/alglie.gi index d682f71459..a02197509e 100644 --- a/lib/alglie.gi +++ b/lib/alglie.gi @@ -4105,7 +4105,7 @@ InstallMethod( PreImagesRepresentative, if not ( x in Range( f ) ) then return fail; fi; - return PreImagesRepresentative( f, x ); + return PreImagesRepresentativeNC( f, x ); end ); diff --git a/lib/field.gi b/lib/field.gi index 6223cf0535..2d852cef73 100644 --- a/lib/field.gi +++ b/lib/field.gi @@ -1340,7 +1340,7 @@ InstallMethod( PreImagesElm, if not (elm in Range(hom)) then return fail; fi; - return PreImagesElm( hom, elm ); + return PreImagesElmNC( hom, elm ); end ); ############################################################################# @@ -1367,6 +1367,6 @@ InstallMethod( PreImagesSet, if not IsSubset( Range(hom), elms ) then return fail; fi; - return PreImagesSet( hom, elms ); + return PreImagesSetNC( hom, elms ); end ); diff --git a/lib/liefam.gi b/lib/liefam.gi index 0f9f70c53f..0a6e4b2a25 100644 --- a/lib/liefam.gi +++ b/lib/liefam.gi @@ -465,7 +465,7 @@ InstallMethod( PreImagesElm, if not ( elm in Range(emb) ) then return fail; fi; - return PreImagesElm( emb, elm ); + return PreImagesElmNC( emb, elm ); end ); ############################################################################# diff --git a/lib/mapping.gd b/lib/mapping.gd index 93862917a5..4feb438311 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -980,10 +980,13 @@ DeclareGlobalFunction( "Images" ); ## map then returns the set of all ## preimages of elm under map. ##

-## From &GAP; version 4.16.0 +## From &GAP; version 4.16.1 ## PreImagesElm was renamed PreImagesElmNC ## throughout the library, and PreImagesElm now checks that -## elm is an element of the range before calling PreImagesElmNC. +## elm is an element of the image before calling PreImagesElmNC. +## If elm is not in the range then an error is thrown. +## If elm is in the range but not in the image then fail +## is returned. ##

## When using PreImagesElmNC anything may happen if elm ## is not an element of the range of map. @@ -1037,10 +1040,13 @@ DeclareOperation( "PreImageElm", ## fail, the latter if and only if elm ## has no preimages under map. ##

-## From &GAP; version 4.16.0 PreImagesRepresentative +## From &GAP; version 4.16.1 PreImagesRepresentative ## was renamed PreImagesRepresentativeNC throughout the library, ## and PreImagesRepresentative now checks that elm is an -## element of the range before calling PreImagesRepresentativeNC. +## element of the image before calling PreImagesRepresentativeNC. +## If elm is not in the range then an error is thrown. +## If elm is in the range but not in the image then fail +## is returned. ##

## When using PreImagesRepresentativeNC anything may happen if ## elm is not an element of the range of map. @@ -1068,10 +1074,13 @@ DeclareOperation( "PreImagesRepresentativeNC", [ IsGeneralMapping, IsObject ] ); ## then returns the set of all preimages of ## elms under map. ##

-## From &GAP; version 4.16.0 PreImagesSet +## From &GAP; version 4.16.1 PreImagesSet ## has been renamed PreImagesSetNC throughout the library, ## and PreImagesSet now checks that elms is a -## subset of the range before calling PreImagesSetNC. +## subset of the image before calling PreImagesSetNC. +## If elms is not a subset of the range then an error is thrown. +## If elm is a subset the range but not a subset of the image then +## fail is returned. ##

## When using PreImagesSetNC anything may happen if elms ## is not a subset of the range of map. @@ -1189,10 +1198,14 @@ DeclareGlobalFunction( "PreImage" ); ## and to resp. when ## called with two arguments. ##

-## From &GAP; version 4.16.0 PreImages +## From &GAP; version 4.16.1 PreImages ## has been renamed PreImagesNC throughout the library, ## and PreImages now checks that elm or coll -## belong to the range before calling PreImagesNC. +## belong to the image before calling PreImagesNC. +## If elm or coll are not contained in the range +## then an error is thrown. +## If elm or coll are contained in the range but not in the +## image then fail is returned. ##

## When using PreImagesNC anything may happen if elm ## or coll do not belong to the range of map. diff --git a/lib/mapping.gi b/lib/mapping.gi index 5069534ba6..9233092ec1 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -319,24 +319,12 @@ InstallGlobalFunction( PreImagesNC, function ( arg ) map := arg[1]; img := arg[2]; - if not IsGeneralMapping( map ) then - ErrorNoReturn( " must be a general mapping" ); - fi; - # preimage of a single element under - if FamRangeEqFamElm( FamilyObj( map ), FamilyObj( img ) ) then - if not img in Range( map ) then - ErrorNoReturn( " must be an element of Range()" ); - fi; + if FamRangeEqFamElm( FamilyObj( map ), FamilyObj( img ) ) then return PreImagesElmNC( map, img ); # preimage of a collection of elements under elif CollFamRangeEqFamElms( FamilyObj( map ), FamilyObj( img ) ) then - if not IsSubset( Range( map ), img ) then - ErrorNoReturn( "the collection must be contained in ", - "Range()" ); - fi; - if IsDomain( img ) or IsSSortedList( img ) then return PreImagesSetNC( map, img ); elif IsHomogeneousList( img ) then @@ -345,15 +333,9 @@ InstallGlobalFunction( PreImagesNC, function ( arg ) # preimage of the empty list elif IsList( img ) and IsEmpty( img ) then - return []; else - ErrorNoReturn( "the families of the element or collection ", - "and Range() don't match, ", - "maybe is not contained in Range() or ", - "is not a homogeneous list or collection" ); - fi; fi; ErrorNoReturn( "usage: PreImagesNC(), PreImagesNC(,), ", "PreImagesNC(,)" ); @@ -1158,7 +1140,7 @@ InstallMethod( PreImagesElm, [ IsGeneralMapping, IsObject ], 0, function ( map, elm ) - if not ( elm in Image( map ) ) then + if not ( elm in Range( map ) ) then return fail; else return PreImagesElmNC( map, elm ); @@ -1191,7 +1173,7 @@ InstallMethod( PreImagesElm, FamRangeEqFamElm, [ IsGeneralMapping and IsConstantTimeAccessGeneralMapping, IsObject ], 0, function( map, elm ) - if not ( elm in Image( map ) ) then + if not ( elm in Range( map ) ) then return fail; else return PreImagesElmNC( map, elm ); @@ -1226,16 +1208,14 @@ InstallMethod( PreImagesSet, CollFamRangeEqFamElms, [ IsGeneralMapping, IsCollection ], 0, function( map, elms ) - local im, elm; if not IsFinite( elms ) then TryNextMethod(); fi; - im:= Image( map ); - for elm in Enumerator( elms ) do - if not (elm in im ) then - return fail; - fi; - od; + if not IsSubset( Range( map ), elms ) then + Error( " is not a subset of the range of " ); + elif not IsSubset( Image( map ), elms ) then + return fail; + fi; return PreImagesSetNC( map, elms ); end ); @@ -1252,7 +1232,7 @@ InstallMethod( PreImagesSet, true, [ IsGeneralMapping, IsList and IsEmpty ], 0, function( map, elms ) - return []; + return []; end ); @@ -1289,7 +1269,13 @@ InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, [ IsSPGeneralMapping, IsObject ], 0, function( map, elm ) - Error( "no default method for s.p. general mapping" ); + if not elm in Range( map ) then + Error( " is not in the range of " ); + elif not elm in Image( map ) then + return fail; + else + return PreImagesRepresentativeNC( map, elm ); + fi; end ); InstallMethod( PreImagesRepresentativeNC, @@ -1330,7 +1316,9 @@ InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, [ IsNonSPGeneralMapping, IsObject ], 0, function( map, elm ) - if not elm in Image( map ) then + if not elm in Range( map ) then + Error( " is not in the range of " ); + elif not elm in Image( map ) then return fail; fi; return PreImagesRepresentativeNC( map, elm ); diff --git a/lib/mapprep.gi b/lib/mapprep.gi index 8be5d05fc6..38f650574b 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -356,7 +356,9 @@ InstallMethod( PreImagesSet, [ IsCompositionMappingRep, IsCollection ], 0, function( com, elms ) if not IsSubset( Range(com), elms ) then - return []; + Error( " is not a subset of the range of map " ); + elif not IsSubset( Image(com), elms ) then + return fail; fi; return PreImagesSetNC( com, elms ); end ); @@ -399,8 +401,10 @@ InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, [ IsCompositionMappingRep, IsObject ], 0, function( com, elm ) - if not ( elm in Range(com) ) then - return fail; + if not elm in Range(com) then + Error( " is not in the range of mapping " ); + elif not elm in Image(com) then + return fail; fi; return PreImagesRepresentativeNC( com, elm ); end ); @@ -1168,7 +1172,9 @@ InstallMethod( PreImagesSet, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsCollection ], 0, function ( inv, elms ) if not IsSubset( Range(inv), elms ) then - return []; + Error( "" ); + elif not IsSubset( Image(inv), elms ) then + return fail; fi; return PreImagesSetNC( inv, elms ); end ); @@ -1192,8 +1198,10 @@ InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, [ IsInverseGeneralMappingRep, IsObject ], 0, function ( inv, elm ) - if not ( elm in Range(inv) ) then - return fail; + if not elm in Range(inv) then + Error( " is not in the range of mapping " ); + elif not elm in Image(inv) then + return fail; fi; return PreImagesRepresentativeNC( inv, elm ); end ); @@ -1447,7 +1455,9 @@ InstallMethod( PreImagesSet, SUM_FLAGS, # can't do better function ( id, elms ) if not IsSubset( Range(id), elms ) then - return []; + Error( " is not a subset of the mapping " ); + elif not IsSubset( Image(id), elms ) then + return fail; fi; return PreImagesSetNC( id, elms ); end ); @@ -1747,8 +1757,10 @@ InstallMethod( PreImagesElm, FamRangeEqFamElm, [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS, function( zero, elm ) - if not ( elm in Range(zero) ) then - return []; + if not elm in Range(zero) then + Error( " is not i9n the range of mapping " ); + elif not elm in Im age(zero) then + return fail; fi; return PreImagesElmNC( zero, elm ); end ); @@ -1777,7 +1789,9 @@ InstallMethod( PreImagesSet, [ IsGeneralMapping and IsZero, IsCollection ], SUM_FLAGS, function( zero, elms ) if not IsSubset( Range(zero), elms ) then - return []; + Error( " is not a subset of the range of mapping " ); + elif not IsSubset( Image(zero), elms ) then + return fail; fi; return PreImagesSetNC( zero, elms ); end ); @@ -1805,7 +1819,9 @@ InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS, function( zero, elm ) - if not ( elm in Range(zero) ) then + if not elm in Range(zero) then + Error( " is not in the range of mapping " ); + elif mot elm in Image(zero) then return fail; fi; return PreImagesRepresentativeNC( zero, elm ); @@ -2053,7 +2069,9 @@ InstallMethod( PreImagesSet, [ IsGeneralRestrictedMappingRep, IsCollection ], 0, function( res, elms ) if not IsSubset( Range(res), elms ) then - return []; + Error( is not in the range of mapping " ); + elif not IsSubset( Image(res), elms ) then + return fail; fi; return PreImagesSetNC( res, elms ); end ); diff --git a/lib/mgmring.gi b/lib/mgmring.gi index d4d0771b79..534042435a 100644 --- a/lib/mgmring.gi +++ b/lib/mgmring.gi @@ -1242,9 +1242,11 @@ InstallMethod( PreImagesElm, [ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ], function ( emb, elm ) if not ( elm in Range( emb ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( emb ) ) then return fail; fi; - return PreImagesElm( emb, elm ); + return PreImagesElmNC( emb, elm ); end ); InstallMethod( PreImagesRepresentativeNC, @@ -1269,6 +1271,8 @@ InstallMethod( PreImagesRepresentative, [ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ], function ( emb, elm ) if not ( elm in Range( emb ) ) then + Error( " is not in the range of the mapping " ); + elif not ( elm in Image( emb ) ) then return fail; fi; return PreImagesRepresentativeNC( emb, elm ); @@ -1368,6 +1372,8 @@ InstallMethod( PreImagesElm, [ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ], function ( emb, elm ) if not ( elm in Range( emb ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( emb ) ) then return fail; fi; return PreImagesElmNC( emb, elm ); @@ -1395,6 +1401,8 @@ InstallMethod( PreImagesRepresentative, [ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ], function ( emb, elm ) if not ( elm in Range( emb ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( emb ) ) then return fail; fi; return PreImagesRepresentativeNC( emb, elm ); diff --git a/lib/relation.gi b/lib/relation.gi index db6005a732..81bdefef59 100644 --- a/lib/relation.gi +++ b/lib/relation.gi @@ -206,9 +206,9 @@ InstallGlobalFunction(BinaryRelationByElements, ## #P IsReflexiveBinaryRelation() ## -InstallMethod(IsReflexiveBinaryRelation, - "reflexive test binary relation", true, - [IsBinaryRelation], 0, +InstallMethod( IsReflexiveBinaryRelation, + "reflexive test binary relation", true, + [IsBinaryRelation], 0, function(m) local e; @@ -233,7 +233,7 @@ InstallMethod(IsReflexiveBinaryRelation, ## Depends on Images and PreimagesNC returning SSorted lists. ## -InstallMethod(IsSymmetricBinaryRelation, +InstallMethod( IsSymmetricBinaryRelation, "symmetric test binary relation", true, [IsBinaryRelation], 0, function(m) local e,el; @@ -263,7 +263,7 @@ InstallMethod(IsSymmetricBinaryRelation, ## ## Assumes that Images returns a sorted list ## -InstallMethod(IsTransitiveBinaryRelation, +InstallMethod( IsTransitiveBinaryRelation, "transitive test binary relation", true, [IsBinaryRelation], 0, function(m) local e,el,i,im; @@ -294,7 +294,7 @@ InstallMethod(IsTransitiveBinaryRelation, ## #P IsAntisymmetricBinaryRelation() ## -InstallMethod(IsAntisymmetricBinaryRelation, +InstallMethod( IsAntisymmetricBinaryRelation, "test for Antisymmetry of a binary relation", true, [IsBinaryRelation], 0, function(rel) @@ -325,7 +325,7 @@ InstallMethod(IsAntisymmetricBinaryRelation, ## #P IsPreOrderBinaryRelation() ## -InstallMethod(IsPreOrderBinaryRelation, +InstallMethod( IsPreOrderBinaryRelation, "test for whether a binary relation is a preorder", true, [IsBinaryRelation], 0, function(rel) @@ -339,7 +339,7 @@ InstallMethod(IsPreOrderBinaryRelation, ## #P IsPartialOrderBinaryRelation() ## -InstallMethod(IsPartialOrderBinaryRelation, +InstallMethod( IsPartialOrderBinaryRelation, "test for whether a binary relation is a partial order", true, [IsBinaryRelation], 0, function(rel) @@ -354,7 +354,7 @@ InstallMethod(IsPartialOrderBinaryRelation, ## #P IsPartialOrderBinaryRelation() ## -InstallMethod(IsLatticeOrderBinaryRelation, +InstallMethod( IsLatticeOrderBinaryRelation, "test for whether a binary relation is a lattice order", true, [IsBinaryRelation],0, function(rel) @@ -394,7 +394,7 @@ end); ## #P IsEquivalenceRelation() ## -InstallMethod(IsEquivalenceRelation, +InstallMethod( IsEquivalenceRelation, "test for equivalence relation", true, [IsBinaryRelation], 0, function(rel) @@ -424,7 +424,7 @@ InstallMethod(IsEquivalenceRelation, ## is not finite. Can install more specific methods for relations over ## infinite domains where we can do better. ## -InstallMethod(ReflexiveClosureBinaryRelation, +InstallMethod( ReflexiveClosureBinaryRelation, "for binary relation", true, [IsBinaryRelation], 0, function(r) local ur,i,d, newrel; @@ -469,7 +469,7 @@ InstallMethod(ReflexiveClosureBinaryRelation, ## is not finite. Can install more specific methods for relations over ## infinite domains where we can do better. ## -InstallMethod(SymmetricClosureBinaryRelation, +InstallMethod( SymmetricClosureBinaryRelation, "for binary relation", true, [IsBinaryRelation], 0, function(r) local ur,i,t,d, newrel; @@ -513,7 +513,7 @@ InstallMethod(SymmetricClosureBinaryRelation, ## is not finite. Can install more specific methods for relations over ## infinite domains where we can do better. ## -InstallMethod(TransitiveClosureBinaryRelation, +InstallMethod( TransitiveClosureBinaryRelation, "for binary relation", true, [IsBinaryRelation], 0, function(r) @@ -583,7 +583,7 @@ InstallMethod(TransitiveClosureBinaryRelation, ## If is a partial order then return the smallest relation contained ## in whose reflexive and transitive closure is equal to ## -InstallMethod(HasseDiagramBinaryRelation, +InstallMethod( HasseDiagramBinaryRelation, "for binary relation", true, [IsBinaryRelation], 0, function(rel) @@ -690,7 +690,7 @@ InstallGlobalFunction(PartialOrderByOrderingFunction, ## ## returns an equivalence relation on the vertices of the relation. ## -InstallMethod(StronglyConnectedComponents, "for general binary relations", +InstallMethod( StronglyConnectedComponents, "for general binary relations", true, [IsBinaryRelation],0, function(rel) local r, # representation of rel as a binary relation on points @@ -854,43 +854,43 @@ InstallGlobalFunction(RandomBinaryRelationOnPoints, #P IsEquivalenceRelation() ## ## -InstallMethod(IsReflexiveBinaryRelation, "for binary relations on points", +InstallMethod( IsReflexiveBinaryRelation, "for binary relations on points", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep],0, rel -> ForAll([1..DegreeOfBinaryRelation(rel)], i->i in Successors(rel)[i]) ); -InstallMethod(IsSymmetricBinaryRelation, "for binary relations on points", +InstallMethod( IsSymmetricBinaryRelation, "for binary relations on points", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep],0, rel -> ForAll([1..DegreeOfBinaryRelation(rel)], i-> ForAll(Successors(rel)[i], j-> i in Successors(rel)[j] )) ); -InstallMethod(IsTransitiveBinaryRelation, "for binary relations on points", +InstallMethod( IsTransitiveBinaryRelation, "for binary relations on points", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep],0, rel -> ForAll([1..DegreeOfBinaryRelation(rel)], i-> ForAll(Successors(rel)[i], j-> IsSubset(Successors(rel)[i],Successors(rel)[j]))) ); -InstallMethod(IsAntisymmetricBinaryRelation, "for binary relations on points", +InstallMethod( IsAntisymmetricBinaryRelation, "for binary relations on points", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep],0, rel -> ForAll([1..DegreeOfBinaryRelation(rel)], i-> ForAll(Successors(rel)[i], j-> j=i or (not j=i and not i in Successors(rel)[j]))) ); -InstallMethod(IsPreOrderBinaryRelation, "for binary relations on points", +InstallMethod( IsPreOrderBinaryRelation, "for binary relations on points", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep],0, rel -> IsReflexiveBinaryRelation(rel) and IsTransitiveBinaryRelation(rel) ); -InstallMethod(IsPartialOrderBinaryRelation, "for binary relations on points", +InstallMethod( IsPartialOrderBinaryRelation, "for binary relations on points", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep],0, rel -> IsPreOrderBinaryRelation(rel) and IsAntisymmetricBinaryRelation(rel) ); -InstallMethod(IsEquivalenceRelation, "for binary relations on points", +InstallMethod( IsEquivalenceRelation, "for binary relations on points", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep],0, rel -> IsReflexiveBinaryRelation(rel) and IsSymmetricBinaryRelation(rel) and IsTransitiveBinaryRelation(rel) @@ -909,14 +909,14 @@ InstallMethod(IsEquivalenceRelation, "for binary relations on points", #O TransitiveClosureBinaryRelation() ## ## -InstallMethod(ReflexiveClosureBinaryRelation, "for binary relations on points", +InstallMethod( ReflexiveClosureBinaryRelation, "for binary relations on points", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep],0, rel -> BinaryRelationOnPointsNC( List([1..DegreeOfBinaryRelation(rel)], i-> Union2(Successors(rel)[i],[i]))) ); -InstallMethod(SymmetricClosureBinaryRelation, "for binary relations on points", +InstallMethod( SymmetricClosureBinaryRelation, "for binary relations on points", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep],0, function(rel) local suc, #successors of given relation @@ -938,7 +938,7 @@ InstallMethod(SymmetricClosureBinaryRelation, "for binary relations on points", return newrel; end); -InstallMethod(TransitiveClosureBinaryRelation, "for binary relations on points", +InstallMethod( TransitiveClosureBinaryRelation, "for binary relations on pts", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep],0, function(rel) local i,j, #index variables @@ -971,7 +971,7 @@ InstallMethod(TransitiveClosureBinaryRelation, "for binary relations on points", ## ## For binary relations over [1..n] represented as a list of images ## -InstallMethod(ImagesElm, +InstallMethod( ImagesElm, "for binary relations over [1..n] with images list", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep, IsPosInt], 0, function( rel, n ) @@ -988,7 +988,7 @@ InstallMethod(ImagesElm, ## ## For binary relations over [1..n] represented as a list of images ## -InstallMethod(PreImagesElmNC, +InstallMethod( PreImagesElmNC, "for binary rels over [1..n] with images list", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep, IsPosInt], 0, function( rel, n ) @@ -996,14 +996,16 @@ InstallMethod(PreImagesElmNC, i->n in Successors(rel)[i]); end); -InstallMethod(PreImagesElm, +InstallMethod( PreImagesElm, "for binary rels over [1..n] with images list", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep, IsPosInt], 0, function( rel, n ) if not ( n in Range(rel) ) then + Error( "n is not in the range of " ); + elif not ( n in Image(rel) ) then return fail; fi; - return PreImagesElm( rel, n ); + return PreImagesElmNC( rel, n ); end ); ############################################################################# @@ -1013,7 +1015,7 @@ InstallMethod(PreImagesElm, ## Returns the list of images of a binary relation. If the underlying ## domain of the relation is not [1..n] then an error is signalled. ## -InstallMethod(Successors, "for a generic relation", true, +InstallMethod( Successors, "for a generic relation", true, [IsBinaryRelation], 0, function(r) local eldom; # Elements of the domain @@ -1267,7 +1269,7 @@ InstallMethod( One, "for binary relation on points and a set of integers",true, ## ## Display binary relation on n points. ## -InstallMethod(PrintObj, "for a binary relation on n points", true, +InstallMethod( PrintObj, "for a binary relation on n points", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep],0, function(rel) Print("Binary Relation on ",DegreeOfBinaryRelation(rel)," points"); @@ -1663,7 +1665,7 @@ InstallMethod( MeetEquivalenceRelations, #A GeneratorsOfEquivalenceRelationPartition( ) ## ## -InstallMethod(GeneratorsOfEquivalenceRelationPartition, +InstallMethod( GeneratorsOfEquivalenceRelationPartition, "generators for an equivalence with a partition", true, [IsEquivalenceRelation], 0, function(equiv) @@ -1684,7 +1686,7 @@ InstallMethod(GeneratorsOfEquivalenceRelationPartition, ## #M \= for equivalence relations ## -InstallMethod(\=, "for eqivalence relations", IsIdenticalObj, +InstallMethod( \=, "for eqivalence relations", IsIdenticalObj, [IsEquivalenceRelation, IsEquivalenceRelation], 0, function(x, y) @@ -1751,7 +1753,7 @@ InstallMethod(\=, "for eqivalence relations", IsIdenticalObj, ## It has been given a +1 rank which WILL NEED TUNING when the ## other methods are in. ## -InstallMethod(\in, "for eq relation with partition", true, +InstallMethod( \in, "for eq relation with partition", true, [IsList, IsEquivalenceRelation and HasEquivalenceRelationPartition], 1, function(tup, rel) local f; # first block that contains first tuple component @@ -1805,6 +1807,8 @@ InstallMethod( PreImagesRepresentative, "equivalence relations", FamRangeEqFamElm, [IsEquivalenceRelation, IsObject], 0, function( map, elm ) if not ( elm in Range(map) ) then + Error( " is not in the range of " ); + elif not ( elm in Image(map) ) then return fail; fi; return elm; @@ -1854,7 +1858,9 @@ InstallMethod( PreImagesElm, [IsEquivalenceRelation and HasEquivalenceRelationPartition, IsObject],0, function( rel, elm ) - if not ( elm in Range( rel ) ) then ##?? is there a Range(rel)? + if not ( elm in Range( rel ) ) then ## ?? is there a Range(rel)? + Error( " not in the range of " ); + elif not ( elm in Image( rel ) ) then ## ?? is there an Image(rel)? return fail; fi; return PreImagesElmNC( rel, elm ); @@ -1876,7 +1882,7 @@ InstallMethod( PrintObj, "for an equivalence relation", true, ## ## Wraparound function which calls the two-argument method ## -InstallMethod(EquivalenceClasses, "wraparound to call 2-argument version", +InstallMethod( EquivalenceClasses, "wraparound to call 2-argument version", true, [IsEquivalenceRelation], 0, e->EquivalenceClasses(e, UnderlyingDomainOfBinaryRelation(e)) ); @@ -1889,7 +1895,7 @@ InstallMethod(EquivalenceClasses, "wraparound to call 2-argument version", ## This generic method will not terminate for an equivalence over an ## infinite set. ## -InstallOtherMethod(EquivalenceClasses, "for a generic equivalence relation", +InstallOtherMethod( EquivalenceClasses, "for a generic equivalence relation", true, [IsEquivalenceRelation, IsCollection], 0, function(E, D) @@ -1956,7 +1962,7 @@ InstallOtherMethod(EquivalenceClasses, "for a generic equivalence relation", ## membership tests (for example when checking membership of a ## transformation in a monoid, we use Greens relations and classes). ## -InstallMethod(EquivalenceClassOfElementNC, "no check", true, +InstallMethod( EquivalenceClassOfElementNC, "no check", true, [IsEquivalenceRelation, IsObject], 0, function(rel, rep) @@ -1971,7 +1977,7 @@ InstallMethod(EquivalenceClassOfElementNC, "no check", true, return new; end); -InstallMethod(EquivalenceClassOfElement, "with checking", true, +InstallMethod( EquivalenceClassOfElement, "with checking", true, [IsEquivalenceRelation, IsObject], 0, function(rel, rep) @@ -1988,7 +1994,7 @@ InstallMethod(EquivalenceClassOfElement, "with checking", true, ## ## Display an equivalence class. ## -InstallMethod(PrintObj, "for an eq. class", true, +InstallMethod( PrintObj, "for an eq. class", true, [IsEquivalenceClass],0, function(c) Print("{", Representative(c),"}"); @@ -2001,7 +2007,7 @@ InstallMethod(PrintObj, "for an eq. class", true, ## Checks whether is contained in the equivalence class ## If is infinite, this will not necessarily terminate. ## -InstallMethod(\in, "for element and equivalence class", true, +InstallMethod( \in, "for element and equivalence class", true, [IsObject, IsEquivalenceClass], 0, function(x, C) local iter; # iterator of the equivalence class @@ -2061,7 +2067,7 @@ InstallMethod( Enumerator, "for equivalence classes", true, ## ## Equality of equivalence classes ## -InstallMethod(\=, "for two equivalence classes", +InstallMethod( \=, "for two equivalence classes", IsIdenticalObj, [IsEquivalenceClass, IsEquivalenceClass], 0, function(x, y) return Representative(x) in y; @@ -2083,7 +2089,7 @@ InstallMethod( \<, "for two equivalence classes", IsIdenticalObj, return RepresentativeSmallest(x1) < RepresentativeSmallest(x2); end ); -InstallMethod(AsPermutation, "for binary relations on points", true, +InstallMethod( AsPermutation, "for binary relations on points", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep], 0, function(rel) if not IsMapping(rel) then diff --git a/lib/vspchom.gi b/lib/vspchom.gi index 7fe397f6bd..0a3cb99849 100644 --- a/lib/vspchom.gi +++ b/lib/vspchom.gi @@ -510,7 +510,7 @@ InstallMethod( PreImagesRepresentative, [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, IsObject ], function( map, elm ) - if not ( elm in Image( map ) ) then + if not ( elm in Range( map ) ) then return fail; fi; return PreImagesRepresentativeNC( map, elm ); @@ -1257,7 +1257,7 @@ InstallMethod( PreImagesRepresentative, [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, IsObject ], function( map, elm ) - if not ( elm in Image( map ) ) then + if not ( elm in Range( map ) ) then return fail; fi; return PreImagesRepresentativeNC( map, elm ); From 4a39d2470bf55629c74a9703869d64c79ca25952 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 8 Jul 2026 20:30:33 +0100 Subject: [PATCH 054/114] made changes suggested by Thomas --- lib/mapping.gi | 2 +- lib/mapprep.gi | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/mapping.gi b/lib/mapping.gi index 9233092ec1..5330647831 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -335,7 +335,7 @@ InstallGlobalFunction( PreImagesNC, function ( arg ) elif IsList( img ) and IsEmpty( img ) then return []; - else + fi; fi; ErrorNoReturn( "usage: PreImagesNC(), PreImagesNC(,), ", "PreImagesNC(,)" ); diff --git a/lib/mapprep.gi b/lib/mapprep.gi index 38f650574b..24d5fd939e 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -1172,7 +1172,7 @@ InstallMethod( PreImagesSet, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsCollection ], 0, function ( inv, elms ) if not IsSubset( Range(inv), elms ) then - Error( "" ); + Error( " is not a subset of the range of mapping " ); elif not IsSubset( Image(inv), elms ) then return fail; fi; @@ -1759,7 +1759,7 @@ InstallMethod( PreImagesElm, function( zero, elm ) if not elm in Range(zero) then Error( " is not i9n the range of mapping " ); - elif not elm in Im age(zero) then + elif not elm in Image(zero) then return fail; fi; return PreImagesElmNC( zero, elm ); @@ -1821,7 +1821,7 @@ InstallMethod( PreImagesRepresentative, function( zero, elm ) if not elm in Range(zero) then Error( " is not in the range of mapping " ); - elif mot elm in Image(zero) then + elif not elm in Image(zero) then return fail; fi; return PreImagesRepresentativeNC( zero, elm ); From f28660d29bbcb6b4cb48d3529bc83d89a701cd50 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 8 Jul 2026 20:42:45 +0100 Subject: [PATCH 055/114] made changes suggested by Thomas --- lib/mapprep.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapprep.gi b/lib/mapprep.gi index 24d5fd939e..07641f5c67 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -2069,7 +2069,7 @@ InstallMethod( PreImagesSet, [ IsGeneralRestrictedMappingRep, IsCollection ], 0, function( res, elms ) if not IsSubset( Range(res), elms ) then - Error( is not in the range of mapping " ); + Error( " is not in the range of mapping " ); elif not IsSubset( Image(res), elms ) then return fail; fi; From 01360af78a360a2adcc350c67294e63e07fb9b77 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 9 Jul 2026 14:16:20 +0100 Subject: [PATCH 056/114] added many error messages and a few methods --- lib/alghom.gi | 6 +++ lib/alglie.gi | 2 + lib/field.gi | 5 +- lib/fldabnum.gi | 6 +++ lib/ghom.gi | 50 +++++++++++++++++-- lib/ghomfp.gi | 4 ++ lib/ghompcgs.gi | 14 ++++++ lib/ghomperm.gi | 65 ++++++++++++++++++++++++ lib/gprdmat.gi | 8 ++- lib/gprdperm.gi | 8 +++ lib/grpmat.gi | 2 + lib/grpnice.gi | 2 + lib/liefam.gi | 2 + lib/mapphomo.gi | 128 ++++++++++++++++++++++++++++++++++++++++++++++-- lib/mapping.gi | 16 +++--- lib/mapprep.gi | 40 ++++++++++----- lib/morpheus.gi | 2 + lib/oprt.gi | 4 ++ lib/relation.gi | 2 +- lib/ringhom.gi | 2 + lib/vspchom.gi | 4 ++ 21 files changed, 341 insertions(+), 31 deletions(-) diff --git a/lib/alghom.gi b/lib/alghom.gi index b28b163047..4b8edbe22c 100644 --- a/lib/alghom.gi +++ b/lib/alghom.gi @@ -596,6 +596,8 @@ InstallMethod( PreImagesRepresentative, IsObject ], function( map, elm ) if not ( elm in Range( map ) ) then + Error( " is not in the range of " ); + elif not ( elm in Image( map ) ) then return fail; fi; return PreImagesRepresentativeNC( map, elm ); @@ -941,6 +943,8 @@ InstallMethod( PreImagesRepresentative, [ IsOperationAlgebraHomomorphismDefaultRep, IsMatrix ], function( ophom, mat ) if not ( mat in Range( ophom ) ) then + Error( " not in the range of mapping " ); + elif not ( mat in Image( ophom ) ) then return fail; fi; return PreImagesRepresentativeOperationAlgebraHomomorphism( ophom, mat ); @@ -1115,6 +1119,8 @@ InstallMethod( PreImagesRepresentative, [ IsAlgebraHomomorphismFromFpRep, IsMatrix ], function( ophom, mat ); if not ( mat in Range( ophom ) ) then + Error( " is not in the range of mapping " ); + elif not ( mat in Image( ophom ) ) then return fail; fi; return PreImagesRepresentativeOperationAlgebraHomomorphism( ophom, mat ); diff --git a/lib/alglie.gi b/lib/alglie.gi index a02197509e..1bb5943403 100644 --- a/lib/alglie.gi +++ b/lib/alglie.gi @@ -4103,6 +4103,8 @@ InstallMethod( PreImagesRepresentative, function( f, x ) if not ( x in Range( f ) ) then + Error( " is not in the range of mapping " ); + elif not ( x in Image( f ) ) then return fail; fi; return PreImagesRepresentativeNC( f, x ); diff --git a/lib/field.gi b/lib/field.gi index 2d852cef73..3788b0be02 100644 --- a/lib/field.gi +++ b/lib/field.gi @@ -1338,6 +1338,8 @@ InstallMethod( PreImagesElm, [ IsFieldHomomorphism, IsObject ], function ( hom, elm ) if not (elm in Range(hom)) then + Error( " is not in the range of " ); + elif not (elm in Image(hom)) then return fail; fi; return PreImagesElmNC( hom, elm ); @@ -1365,8 +1367,9 @@ InstallMethod( PreImagesSet, [ IsFieldHomomorphism, IsField ], function ( hom, elms ) if not IsSubset( Range(hom), elms ) then + Error( " is not a subset of the range of " ); + elif not IsSubset( Image(hom), elms ) then return fail; fi; return PreImagesSetNC( hom, elms ); end ); - diff --git a/lib/fldabnum.gi b/lib/fldabnum.gi index cfc60cc6d9..fcd3524119 100644 --- a/lib/fldabnum.gi +++ b/lib/fldabnum.gi @@ -1936,6 +1936,8 @@ InstallMethod( PreImagesElm, [ IsFieldHomomorphism and IsANFAutomorphismRep, IsScalar ], function ( aut, elm ) if not ( elm in Range(aut) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image(aut) ) then return fail; fi; return PreImagesElmNC( aut, elm ); @@ -1960,6 +1962,8 @@ InstallMethod( PreImagesSet, [ IsFieldHomomorphism and IsANFAutomorphismRep, IsField ], function ( aut, F ) if not IsSubset( Range(aut), F ) then + Error( " is not a subset of the range of mapping " ); + elif not IsSubset( Image(aut), F ) then return fail; fi; return PreImagesSetNC( aut, F ); @@ -1985,6 +1989,8 @@ InstallMethod( PreImagesRepresentative, [ IsFieldHomomorphism and IsANFAutomorphismRep, IsScalar ], function ( aut, elm ) if not ( elm in Range( aut ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( aut ) ) then return fail; fi; return PreImagesRepresentativeNC( aut, elm ); diff --git a/lib/ghom.gi b/lib/ghom.gi index 29caa4a36b..175e6691e1 100644 --- a/lib/ghom.gi +++ b/lib/ghom.gi @@ -274,6 +274,8 @@ InstallMethod( PreImagesRepresentative, "for PBG-Hom", FamRangeEqFamElm, IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) if not ( elm in Range( hom ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( hom ) ) then return fail; fi; return PreImagesRepresentativeNC( hom, elm ); @@ -886,7 +888,8 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesRepresentativeNC( , ) . . . . . . . . . . . . for GHBI +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . . for GHBI +#M PreImagesRepresentative( , ) . . . . . . . . . . . . for GHBI ## InstallMethod( PreImagesRepresentativeNC, "for GHBI and mult.-elm.-with-inverse", @@ -901,6 +904,19 @@ InstallMethod( PreImagesRepresentativeNC, fi; end ); +InstallMethod( PreImagesRepresentative, + "for GHBI and mult.-elm.-with-inverse", + FamRangeEqFamElm, + [ IsGroupGeneralMappingByImages, + IsMultiplicativeElementWithInverse ], 0, +function( hom, elm ) + if not ( elm in Range( hom ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); ############################################################################# ## @@ -1236,7 +1252,8 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesRepresentativeNC( , ) . . . . for conjugator isomorphism +#M PreImagesRepresentativeNC( , ) . . . for conjugator isomorphism +#M PreImagesRepresentative( , ) . . . . for conjugator isomorphism ## InstallMethod( PreImagesRepresentativeNC, "for conjugator isomorphism", @@ -1246,10 +1263,24 @@ InstallMethod( PreImagesRepresentativeNC, return g ^ ( ConjugatorOfConjugatorIsomorphism( hom ) ^ -1 ); end ); +InstallMethod( PreImagesRepresentative, + "for conjugator isomorphism", + FamRangeEqFamElm, + [ IsConjugatorIsomorphism, IsMultiplicativeElementWithInverse ], 0, +function( hom, g ) + if not ( g in Range( hom ) ) then + Error( " is not in the range of mapping " ); + elif not ( g in Image( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, g ); +end ); + ############################################################################# ## -#M PreImagesSetNC( , ) . . . . . . . . . for conjugator isomorphism +#M PreImagesSetNC( , ) . . . . . . . . for conjugator isomorphism +#M PreImagesSet( , ) . . . . . . . . . for conjugator isomorphism ## InstallMethod( PreImagesSetNC, "for conjugator isomorphism, and group", @@ -1259,6 +1290,19 @@ InstallMethod( PreImagesSetNC, return U ^ ( ConjugatorOfConjugatorIsomorphism( hom ) ^ -1 ); end ); +InstallMethod( PreImagesSet, + "for conjugator isomorphism, and group", + CollFamRangeEqFamElms, + [ IsConjugatorIsomorphism, IsGroup ], 0, +function( hom, U ) + if not IsSubset( Range( hom ), U ) then + Error( " is not a subset of the range of mapping " ); + elif not IsSubset( Image( hom ), U ) then + return fail; + fi; + return PreImagesSetNC( hom, U ); +end ); + ############################################################################# ## diff --git a/lib/ghomfp.gi b/lib/ghomfp.gi index 86d7fa5a9f..df5689705b 100644 --- a/lib/ghomfp.gi +++ b/lib/ghomfp.gi @@ -630,6 +630,8 @@ InstallMethod( PreImagesSet, "map from (sub)group of fp group", [ IsFromFpGroupHomomorphism,IsGroup ],0, function(hom,u) if not IsSubset( Range(hom), u ) then + Error( " is not a subset of the range of " ); + elif not IsSubset( Image(hom), u ) then return fail; fi; return PreImagesSetNC(hom,u); @@ -766,6 +768,8 @@ InstallMethod( PreImagesRepresentative, 1, function(hom,elm) if not (elm in Range(hom)) then + Error( " is not in the range of mapping " ); + elif not (elm in Image(hom)) then return fail; fi; return PreImagesRepresentativeNC(hom,elm); diff --git a/lib/ghompcgs.gi b/lib/ghompcgs.gi index 984f80f3f3..7640a62a57 100644 --- a/lib/ghompcgs.gi +++ b/lib/ghompcgs.gi @@ -536,6 +536,8 @@ InstallMethod( PreImagesRepresentative, "method for pcgs hom", [ IsToPcGroupHomomorphismByImages,IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) if not ( elm in Range( hom ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( hom ) ) then return fail; fi; return PreImagesRepresentativeNC( hom, elm ); @@ -639,6 +641,7 @@ end ); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . . . . via depth map +#M PreImagesRepresentative( , ) . . . . . . . . . . via depth map ## InstallMethod( PreImagesRepresentativeNC, FamRangeEqFamElm, [ IsPcgsToPcgsHomomorphism,IsMultiplicativeElementWithInverse ], 0, @@ -648,6 +651,17 @@ local exp; return PcElementByExponentsNC( hom!.rangePcgsPreImages, exp ); end ); +InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, + [ IsPcgsToPcgsHomomorphism,IsMultiplicativeElementWithInverse ], 0, +function( hom, elm ) + if not ( elm in Range( hom ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); + ############################################################################# ## #M = . . . . . . . . . . . . . . . . . . . . . . . . for GHBI diff --git a/lib/ghomperm.gi b/lib/ghomperm.gi index 8b5c6a79dd..1ee763a714 100644 --- a/lib/ghomperm.gi +++ b/lib/ghomperm.gi @@ -12,6 +12,7 @@ ############################################################################# ## #M PreImagesSetNC( , ) . for s.p. gen. mapping resp. mult. & inv. +#M PreImagesSet( , ) . . for s.p. gen. mapping resp. mult. & inv. ## InstallMethod( PreImagesSetNC, "method for permgroup homs", @@ -78,6 +79,19 @@ local genpreimages, pre,kg,sz,ol,orb,pos,dom,one; return pre; end ); +InstallMethod( PreImagesSet, + "method for permgroup homs", + CollFamRangeEqFamElms, + [ IsPermGroupHomomorphism, IsGroup ], +function( map, elms ) + if not IsSubset( Range( map ), elms ) then + Error( " is not a subset of the range of " ); + elif not IsSubset( Image( map ), elms ) then + return fail; + fi; + return PreImagesSetNC( map, elms ); +end ); + ############################################################################# ## #F AddGeneratorsGenimagesExtendSchreierTree( , , ) . . @@ -1177,6 +1191,8 @@ InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) if not ( elm in Range( hom ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( hom ) ) then return fail; fi; return PreImagesRepresentativeNC( hom, elm ); @@ -1574,6 +1590,7 @@ InstallMethod( ImagesSource,"constituent homomorphism",true, ############################################################################# ## #M PreImagesRepresentativeNC( , ) +#M PreImagesRepresentative( , ) ## InstallMethod( PreImagesRepresentativeNC,"constituent homomorphism", FamRangeEqFamElm,[IsConstituentHomomorphism,IsPerm], 0, @@ -1588,9 +1605,21 @@ local D,DP; return RepresentativeAction(Source(hom),D,DP,OnTuples); end); +InstallMethod( PreImagesRepresentative,"constituent homomorphism", + FamRangeEqFamElm,[IsConstituentHomomorphism,IsPerm], 0, +function( hom, elm ) + if not ( elm in Range( hom ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); + ############################################################################# ## #M PreImagesSetNC( , ) . . . . . . . . . . . . . . . for const hom +#M PreImagesSet( , ) . . . . . . . . . . . . . . . . for const hom ## InstallMethod( PreImagesSetNC, "constituent homomorphism",CollFamRangeEqFamElms, [ IsConstituentHomomorphism, IsPermGroup ], 0, @@ -1621,6 +1650,17 @@ InstallMethod( PreImagesSetNC, "constituent homomorphism",CollFamRangeEqFamElms, return GroupStabChain( Source( hom ), H, true ); end ); +InstallMethod( PreImagesSet, "constituent homomorphism",CollFamRangeEqFamElms, + [ IsConstituentHomomorphism, IsPermGroup ], 0, + function( hom, I ) + if not IsSubset( Range( hom ), I ) then + Error( " is not a subset of the range of mapping " ); + elif not IsSubset( Image( hom ), I ) then + return fail; + fi; + return PreImagesSetNC( hom, I ); +end ); + ############################################################################# ## #M KernelOfMultiplicativeGeneralMapping( ) . . . . . . . for const hom @@ -1829,6 +1869,7 @@ end ); ############################################################################# ## #M PreImagesRepresentativeNC( , ) . . . . . . . . for blocks hom +#M PreImagesRepresentative( , ) . . . . . . . . . for blocks hom ## InstallMethod( PreImagesRepresentativeNC, "blocks homomorphism", FamRangeEqFamElm, @@ -1878,9 +1919,22 @@ InstallMethod( PreImagesRepresentativeNC, "blocks homomorphism", return pre; end) ; +InstallMethod( PreImagesRepresentative, "blocks homomorphism", + FamRangeEqFamElm, + [ IsBlocksHomomorphism, IsMultiplicativeElementWithInverse ], 0, + function( hom, elm ) + if not ( elm in Range( hom ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); + ############################################################################# ## #M PreImagesSetNC( , ) . . . . . . . . . . . . . . for blocks hom +#M PreImagesSet( , ) . . . . . . . . . . . . . . . for blocks hom ## InstallMethod( PreImagesSetNC, CollFamRangeEqFamElms, [ IsBlocksHomomorphism, IsPermGroup ], 0, @@ -1891,6 +1945,17 @@ InstallMethod( PreImagesSetNC, CollFamRangeEqFamElms, return GroupStabChain( Source( hom ), H, true ); end ); +InstallMethod( PreImagesSet, CollFamRangeEqFamElms, + [ IsBlocksHomomorphism, IsPermGroup ], 0, + function( hom, I ) + if not IsSubset( Range( hom ), I ) then + Error( " is not a subset of the range of mapping " ); + elif not IsSubset( Image( hom ), I ) then + return fail; + fi; + return PreImagesSetNC( hom, I ); +end ); + ############################################################################# ## #F PreImageSetStabBlocksHomomorphism( , ) . . . recursive function diff --git a/lib/gprdmat.gi b/lib/gprdmat.gi index d73b63e568..a94623e6ac 100644 --- a/lib/gprdmat.gi +++ b/lib/gprdmat.gi @@ -169,6 +169,8 @@ InstallMethod(PreImagesRepresentative,"matrix direct product embedding", IsMultiplicativeElementWithInverse ], function(emb,g) if not (g in Range(emb)) then + Error( " is not in the range of mapping " ); + elif not ( g in Image(emb) ) then return fail; fi; return PreImagesRepresentativeNC(emb,g); @@ -238,7 +240,9 @@ InstallMethod(PreImagesRepresentative,"matrix direct product projection", [ IsProjectionDirectProductMatrixGroup, IsMultiplicativeElementWithInverse ],0, function(prj,m) - if not (m in Range(prj)) then + if not ( m in Range(prj) ) then + Error( " not in the range of mapping " ); + elif not ( m in Image(prj) ) then return fail; fi; return PreImagesRepresentativeNC(prj,m); @@ -432,6 +436,8 @@ InstallMethod( PreImagesRepresentative, IsMultiplicativeElementWithInverse ], 0, function( emb, g ) if not (g in Range(emb)) then + Error( " is not in the range of mapping " ); + elif not (g in Image(emb)) then return fail; fi; return PreImagesRepresentativeNC(emb,g); diff --git a/lib/gprdperm.gi b/lib/gprdperm.gi index 75583f7a0d..e6fc1111aa 100644 --- a/lib/gprdperm.gi +++ b/lib/gprdperm.gi @@ -198,6 +198,8 @@ InstallMethod( PreImagesRepresentative, "perm direct product embedding", IsMultiplicativeElementWithInverse ], function( emb, g ) if not ( g in Range( emb ) ) then + Error( " is not in the range of mapping " ); + elif not ( g in Image( emb ) ) then return fail; fi; return PreImagesRepresentativeNC( emb, g ); @@ -321,6 +323,8 @@ InstallMethod( PreImagesRepresentative,"perm direct product projection", IsMultiplicativeElementWithInverse ], 0, function( prj, g ) if not ( g in Range( prj ) ) then + Error( " is not in the range of mapping " ); + elif not ( g in Image( prj ) ) then return fail; fi; return PreImagesRepresentativeNC( prj, g ); @@ -529,6 +533,8 @@ InstallMethod( PreImagesRepresentative,"perm subdirect product projection", IsMultiplicativeElementWithInverse ], 0, function( prj, img ) if not ( img in Range( prj ) ) then + Error( " is not in the range of mapping " ); + elif not ( img in Image( prj ) ) then return fail; fi; return PreImagesRepresentativeNC( prj, img ); @@ -863,6 +869,8 @@ InstallMethod( PreImagesRepresentative, IsMultiplicativeElementWithInverse ], 0, function( emb, g ) if not ( g in Range( emb ) ) then + Error( " is not in the range of mapping " ); + elif not ( g in Image( emb ) ) then return fail; fi; return PreImagesRepresentativeNC( emb, g ); diff --git a/lib/grpmat.gi b/lib/grpmat.gi index 25d07eab9b..43c407eec7 100644 --- a/lib/grpmat.gi +++ b/lib/grpmat.gi @@ -1262,6 +1262,8 @@ InstallMethod( PreImagesRepresentative, [ IsBlowUpIsomorphism, IsMatrix ], function( iso, mat ) if not ( mat in Range(iso) ) then + Error( " is not in the range of mapping " ); + elif not ( mat in Image(iso) ) then return fail; fi; return PreImagesRepresentativeNC( iso, mat ); diff --git a/lib/grpnice.gi b/lib/grpnice.gi index 014b64e30d..85fadf1555 100644 --- a/lib/grpnice.gi +++ b/lib/grpnice.gi @@ -1002,6 +1002,8 @@ InstallMethod( PreImagesRepresentative, "for PBG-Niceo", IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) if not ( elm in Range(hom) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image(hom) ) then return fail; fi; return PreImagesRepresentativeNC( hom, elm ); diff --git a/lib/liefam.gi b/lib/liefam.gi index 0a6e4b2a25..f0fafb4e8f 100644 --- a/lib/liefam.gi +++ b/lib/liefam.gi @@ -463,6 +463,8 @@ InstallMethod( PreImagesElm, IsLieObject and IsPackedElementDefaultRep ], 0, function( emb, elm ) if not ( elm in Range(emb) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image(emb) ) then return fail; fi; return PreImagesElmNC( emb, elm ); diff --git a/lib/mapphomo.gi b/lib/mapphomo.gi index fbd38cb004..10658ecf0c 100644 --- a/lib/mapphomo.gi +++ b/lib/mapphomo.gi @@ -331,6 +331,7 @@ InstallMethod( ImagesSet, ############################################################################# ## #M PreImagesElmNC( , ) . for s.p. gen. mapping resp. mult. & inv. +#M PreImagesElm( , ) . . for s.p. gen. mapping resp. mult. & inv. ## InstallMethod( PreImagesElmNC, "method for s.p. general mapping respecting mult. & inv., and element", @@ -348,6 +349,20 @@ InstallMethod( PreImagesElmNC, fi; end ); +InstallMethod( PreImagesElm, + "method for s.p. general mapping respecting mult. & inv., and element", + FamRangeEqFamElm, + [ IsSPGeneralMapping and RespectsMultiplication and RespectsInverses, + IsObject ], +function( map, elm ) + if not ( elm in Range( map ) ) then + Error( " is not in the range of " ); + elif not ( elm in Image( map ) ) then + return fail; + fi; + return PreImagesElmNC( map, elm ); +end ); + ############################################################################# ## @@ -384,6 +399,21 @@ InstallMethod( PreImagesSetNC, return pre; end ); +InstallMethod( PreImagesSet, + "method for s.p. general mapping respecting mult. & inv., and group", + CollFamRangeEqFamElms, + [ IsSPGeneralMapping and RespectsMultiplication and RespectsInverses, + IsGroup ], + function( map, elms ) + if not IsSubset( Range( map ), elms ) then + Error( " is not a subset of the range of " ); + elif not IsSubset( Image( map ), elms ) then + return fail; + fi; + return PreImagesSetNC( map, elms ); + end ); + + InstallMethod( PreImagesSetNC, "method for injective s.p. mapping respecting mult. & inv., and group", CollFamRangeEqFamElms, @@ -400,6 +430,21 @@ InstallMethod( PreImagesSetNC, return pre; end ); +InstallMethod( PreImagesSet, + "method for injective s.p. mapping respecting mult. & inv., and group", + CollFamRangeEqFamElms, + [ IsSPGeneralMapping and IsMapping and IsInjective and + RespectsMultiplication and RespectsInverses, + IsGroup ], + function( map, elms ) + if not IsSubset( Range( map ), elms ) then + Error( " is not a subset of the range of " ); + elif not IsSubset( Image( map ), elms ) then + return fail; + fi; + return PreImagesSetNC( map, elms ); + end ); + ############################################################################# ## @@ -685,6 +730,7 @@ InstallMethod( ImagesSet, ############################################################################# ## #M PreImagesElmNC( , ) for s.p. gen. mapping resp. add. & add.inv. +#M PreImagesElm( , ) . for s.p. gen. mapping resp. add. & add.inv. ## InstallMethod( PreImagesElmNC, "method for s.p. gen. mapping respecting add. & add.inv., and element", @@ -702,10 +748,25 @@ InstallMethod( PreImagesElmNC, fi; end ); +InstallMethod( PreImagesElm, + "method for s.p. gen. mapping respecting add. & add.inv., and element", + FamRangeEqFamElm, + [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses, + IsObject ], + function( map, elm ) + if not ( elm in Range( map ) ) then + Error( " is not in the range of " ); + elif not ( elm in Image( map ) ) then + return fail; + fi; + return PreImagesElmNC( map, elm ); + end ); + ############################################################################# ## #M PreImagesSetNC( , ) for s.p. gen. mapp. resp. add. & add.inv. +#M PreImagesSet( , ) . for s.p. gen. mapp. resp. add. & add.inv. ## InstallMethod( PreImagesSetNC, "method for s.p. gen. mapping resp. add. & add.inv., and add. group", @@ -719,13 +780,26 @@ InstallMethod( PreImagesSetNC, if fail in genpreimages then TryNextMethod(); fi; - return SubadditiveGroupNC( Source( map ), Concatenation( GeneratorsOfAdditiveGroup( KernelOfAdditiveGeneralMapping( map ) ), genpreimages ) ); end ); +InstallMethod( PreImagesSet, + "method for s.p. gen. mapping resp. add. & add.inv., and add. group", + CollFamRangeEqFamElms, + [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses, + IsAdditiveGroup ], + function( map, elms ) + if not IsSubset( Range( map ), elms ) then + Error( " is not a subset of the range of " ); + elif not IsSubset( Image( map ), elms ) then + return fail; + fi; + return PreImagesSetNC( map, elms ); + end ); + ############################################################################# ## @@ -891,6 +965,7 @@ InstallMethod( ImagesSet, ############################################################################# ## #M PreImagesSetNC( , ) . . . for linear mapping and left module +#M PreImagesSet( , ) . . . . for linear mapping and left module ## InstallMethod( PreImagesSetNC, "method for linear mapping and left module", @@ -905,13 +980,27 @@ InstallMethod( PreImagesSetNC, if fail in genpreimages then TryNextMethod(); fi; - return SubmoduleNC( Source( map ), Concatenation( GeneratorsOfLeftModule( KernelOfAdditiveGeneralMapping( map ) ), genpreimages ) ); end ); +InstallMethod( PreImagesSet, + "method for linear mapping and left module", + CollFamRangeEqFamElms, + [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses + and RespectsScalarMultiplication, + IsLeftModule ], + function( map, elms ) + if not IsSubset( Range( map ), elms ) then + Error( " is not a subset of the range of " ); + elif not IsSubset( Image( map ), elms ) then + return fail; + fi; + return PreImagesSetNC( map, elms ); + end ); + ############################################################################# ## @@ -985,6 +1074,7 @@ InstallMethod( ImagesSet, ############################################################################# ## #M PreImagesSetNC( , ) . . . . . . . for algebra hom. and FLMLOR +#M PreImagesSet( , ) . . . . . . . . for algebra hom. and FLMLOR ## InstallMethod( PreImagesSetNC, "method for algebra hom. and FLMLOR", @@ -999,7 +1089,6 @@ InstallMethod( PreImagesSetNC, if fail in genpreimages then TryNextMethod(); fi; - return SubFLMLORNC( Source( map ), Concatenation( GeneratorsOfLeftOperatorRing( KernelOfAdditiveGeneralMapping( map ) ), @@ -1007,10 +1096,26 @@ InstallMethod( PreImagesSetNC, #T handle the case of ideals! end ); +InstallMethod( PreImagesSet, + "method for algebra hom. and FLMLOR", + CollFamRangeEqFamElms, + [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses + and RespectsScalarMultiplication and RespectsMultiplication, + IsFLMLOR ], + function( map, elms ) + if not IsSubset( Range( map ), elms ) then + Error( " is not a subset of the range of " ); + elif not IsSubset( Image( map ), elms ) then + return fail; + fi; + return PreImagesSetNC( map, elms ); + end ); + ############################################################################# ## #M PreImagesSetNC( , ) for alg-with-one hom. and FLMLOR-with-one +#M PreImagesSet( , ) . for alg-with-one hom. and FLMLOR-with-one ## InstallMethod( PreImagesSetNC, "method for algebra-with-one hom. and FLMLOR-with-one", @@ -1026,7 +1131,6 @@ InstallMethod( PreImagesSetNC, if fail in genpreimages then TryNextMethod(); fi; - return SubFLMLORNC( Source( map ), Concatenation( GeneratorsOfLeftOperatorRingWithOne( KernelOfAdditiveGeneralMapping( map ) ), @@ -1034,6 +1138,22 @@ InstallMethod( PreImagesSetNC, #T handle the case of ideals! end ); +InstallMethod( PreImagesSet, + "method for algebra-with-one hom. and FLMLOR-with-one", + CollFamRangeEqFamElms, + [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses + and RespectsScalarMultiplication and RespectsMultiplication + and RespectsOne, + IsFLMLORWithOne ], + function( map, elms ) + if not IsSubset( Range( map ), elms ) then + Error( " is not a subset of the range of " ); + elif not IsSubset( Image( map ), elms ) then + return fail; + fi; + return PreImagesSetNC( map, elms ); + end ); + ############################################################################# ## diff --git a/lib/mapping.gi b/lib/mapping.gi index 5330647831..d428e11275 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -1122,7 +1122,6 @@ InstallMethod( PreImagesElmNC, FamRangeEqFamElm, [ IsGeneralMapping, IsObject ], 0, function ( map, elm ) - # for a finite source simply run over the elements of the source if IsFinite( Source( map ) ) then return Filtered( Source( map ), @@ -1139,12 +1138,12 @@ InstallMethod( PreImagesElm, FamRangeEqFamElm, [ IsGeneralMapping, IsObject ], 0, function ( map, elm ) - if not ( elm in Range( map ) ) then + Error( " is not in the range of " ); + elif not ( elm in Image( map ) ) then return fail; - else - return PreImagesElmNC( map, elm ); fi; + return PreImagesElmNC( map, elm ); end ); @@ -1174,10 +1173,11 @@ InstallMethod( PreImagesElm, [ IsGeneralMapping and IsConstantTimeAccessGeneralMapping, IsObject ], 0, function( map, elm ) if not ( elm in Range( map ) ) then + Error( " is not in the range of " ); + elif not ( elm in Image( map ) ) then return fail; - else - return PreImagesElmNC( map, elm ); fi; + return PreImagesElmNC( map, elm ); end ); @@ -1202,15 +1202,11 @@ InstallMethod( PreImagesSetNC, return primgs; end ); - InstallMethod( PreImagesSet, "for general mapping, and finite collection", CollFamRangeEqFamElms, [ IsGeneralMapping, IsCollection ], 0, function( map, elms ) - if not IsFinite( elms ) then - TryNextMethod(); - fi; if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); elif not IsSubset( Image( map ), elms ) then diff --git a/lib/mapprep.gi b/lib/mapprep.gi index 07641f5c67..07ba28d9b1 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -325,6 +325,8 @@ InstallMethod( PreImagesElm, [ IsCompositionMappingRep, IsObject ], 0, function( com, elm ) if not ( elm in Range(com) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image(com) ) then return fail; fi; return PreImagesElmNC( com, elm ); @@ -356,7 +358,7 @@ InstallMethod( PreImagesSet, [ IsCompositionMappingRep, IsCollection ], 0, function( com, elms ) if not IsSubset( Range(com), elms ) then - Error( " is not a subset of the range of map " ); + Error( " is not a subset of the range of mapping " ); elif not IsSubset( Image(com), elms ) then return fail; fi; @@ -401,9 +403,9 @@ InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, [ IsCompositionMappingRep, IsObject ], 0, function( com, elm ) - if not elm in Range(com) then + if not ( elm in Range(com) ) then Error( " is not in the range of mapping " ); - elif not elm in Image(com) then + elif not ( elm in Image(com) ) then return fail; fi; return PreImagesRepresentativeNC( com, elm ); @@ -690,6 +692,8 @@ InstallMethod( PreImagesRepresentative, [ IsMappingByFunctionRep, IsObject ], 0, function ( map, elm ) if not ( elm in Range(map) ) then + Error( " is not in the range of " ); + elif not ( elm in Image(map) ) then return fail; fi; return PreImagesRepresentativeNC( map, elm ); @@ -728,7 +732,9 @@ InstallMethod( PreImagesElm, [ IsMappingByFunctionWithInverseRep, IsObject ], 0, function ( map, elm ) if not ( elm in Range(map) ) then - return []; + Error( " is not in the range of " ); + elif not ( elm in Image(map) ) then + return fail; fi; return PreImagesElmNC( map, elm ); end ); @@ -753,6 +759,8 @@ InstallMethod( PreImagesRepresentative, [ IsMappingByFunctionWithInverseRep, IsObject ], 0, function ( map, elm ) if not ( elm in Range(map) ) then + Error( " is not in the range of " ); + elif not ( elm in Image(map) ) then return fail; fi; return PreImagesRepresentativeNC( map, elm ); @@ -1147,7 +1155,9 @@ InstallMethod( PreImagesElm, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsObject ], 0, function ( inv, elm ) if not ( elm in Range(inv) ) then - return []; + Error( " is not in the range of mapping " ); + elif not ( elm in Image(inv) ) then + return fail; fi; return PreImagesElmNC( inv, elm ); end ); @@ -1428,7 +1438,9 @@ InstallMethod( PreImagesElm, SUM_FLAGS, # can't do better function ( id, elm ) if not ( elm in Range(id) ) then - return []; + Error( " is not in the range of mapping " ); + elif not ( elm in Image(id) ) then + return fail; fi; return PreImagesElmNC( id, elm ); end ); @@ -1455,7 +1467,7 @@ InstallMethod( PreImagesSet, SUM_FLAGS, # can't do better function ( id, elms ) if not IsSubset( Range(id), elms ) then - Error( " is not a subset of the mapping " ); + Error( " is not a subset of the range of mapping " ); elif not IsSubset( Image(id), elms ) then return fail; fi; @@ -1484,6 +1496,8 @@ InstallMethod( PreImagesRepresentative, SUM_FLAGS, # can't do better function ( id, elm ) if not ( elm in Range(id) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image(id) ) then return fail; fi; return elm; @@ -1757,9 +1771,9 @@ InstallMethod( PreImagesElm, FamRangeEqFamElm, [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS, function( zero, elm ) - if not elm in Range(zero) then - Error( " is not i9n the range of mapping " ); - elif not elm in Image(zero) then + if not ( elm in Range(zero) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image(zero) ) then return fail; fi; return PreImagesElmNC( zero, elm ); @@ -2038,6 +2052,8 @@ InstallMethod( PreImagesElm, [ IsGeneralRestrictedMappingRep, IsObject ], 0, function( res, elm ) if not ( elm in Range(res) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image(res) ) then return fail; fi; return PreImagesElmNC( res, elm ); @@ -2069,7 +2085,7 @@ InstallMethod( PreImagesSet, [ IsGeneralRestrictedMappingRep, IsCollection ], 0, function( res, elms ) if not IsSubset( Range(res), elms ) then - Error( " is not in the range of mapping " ); + Error( " is not a subset of the range of mapping " ); elif not IsSubset( Image(res), elms ) then return fail; fi; @@ -2108,6 +2124,8 @@ InstallMethod( PreImagesRepresentative, [ IsGeneralRestrictedMappingRep, IsObject ], 0, function( res, elm ) if not ( elm in Range(res) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image(res) ) then return fail; fi; return PreImagesRepresentativeNC( res, elm ); diff --git a/lib/morpheus.gi b/lib/morpheus.gi index a440d864fc..2dacd6e8a4 100644 --- a/lib/morpheus.gi +++ b/lib/morpheus.gi @@ -1091,6 +1091,8 @@ InstallMethod(PreImagesRepresentative,"AutomGroup Niceomorphism", FamRangeEqFamElm,[IsActionHomomorphismAutomGroup,IsPerm],0, function(hom,elm) if not (elm in Range(hom)) then + Error( " not in the range of mapping " ); + elif not (elm in Image(hom)) then return fail; fi; return PreImagesRepresentativeNC(hom,elm); diff --git a/lib/oprt.gi b/lib/oprt.gi index ad2e47f14a..095dc0cb60 100644 --- a/lib/oprt.gi +++ b/lib/oprt.gi @@ -3421,6 +3421,8 @@ InstallMethod( PreImagesRepresentative,"IsLinearActionHomomorphism", FamRangeEqFamElm, [ IsLinearActionHomomorphism, IsPerm ], 0, function( hom, elm ) if not ( elm in Range( hom ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( hom ) ) then return fail; fi; return PreImagesRepresentativeNC( hom, elm ); @@ -3506,6 +3508,8 @@ InstallMethod( PreImagesRepresentative,"IsProjectiveActionHomomorphism", FamRangeEqFamElm, [ IsProjectiveActionHomomorphism, IsPerm ], 0, function( hom, elm ) if not ( elm in Range( hom ) ) then + Error( " is not in the range of mapping " ); + elif not ( elm in Image( hom ) ) then return fail; fi; return PreImagesRepresentativeNC( hom, elm ); diff --git a/lib/relation.gi b/lib/relation.gi index 81bdefef59..2dfabd66dc 100644 --- a/lib/relation.gi +++ b/lib/relation.gi @@ -1001,7 +1001,7 @@ InstallMethod( PreImagesElm, true, [IsBinaryRelation and IsBinaryRelationOnPointsRep, IsPosInt], 0, function( rel, n ) if not ( n in Range(rel) ) then - Error( "n is not in the range of " ); + Error( " is not in the range of " ); elif not ( n in Image(rel) ) then return fail; fi; diff --git a/lib/ringhom.gi b/lib/ringhom.gi index 887a991704..7205e5b85b 100644 --- a/lib/ringhom.gi +++ b/lib/ringhom.gi @@ -458,6 +458,8 @@ InstallMethod( PreImagesRepresentative, IsObject ], function( map, elm ) if not ( elm in Range( map ) ) then + Error( " is not in the range of " ); + elif not ( elm in Image( map ) ) then return fail; fi; return PreImagesRepresentativeNC( map, elm ); diff --git a/lib/vspchom.gi b/lib/vspchom.gi index 0a3cb99849..04b231a314 100644 --- a/lib/vspchom.gi +++ b/lib/vspchom.gi @@ -511,6 +511,8 @@ InstallMethod( PreImagesRepresentative, IsObject ], function( map, elm ) if not ( elm in Range( map ) ) then + Error( " is not in the range of " ); + elif not ( elm in Image( map ) ) then return fail; fi; return PreImagesRepresentativeNC( map, elm ); @@ -1258,6 +1260,8 @@ InstallMethod( PreImagesRepresentative, IsObject ], function( map, elm ) if not ( elm in Range( map ) ) then + Error( " is not in the range of " ); + elif not ( elm in Image( map ) ) then return fail; fi; return PreImagesRepresentativeNC( map, elm ); From fc31d4e5c08d8c5a3293f6f7826bc5f1758d248c Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 9 Jul 2026 14:31:04 +0100 Subject: [PATCH 057/114] added many error messages and a few methods --- lib/mapphomo.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapphomo.gi b/lib/mapphomo.gi index 10658ecf0c..566b5d6af5 100644 --- a/lib/mapphomo.gi +++ b/lib/mapphomo.gi @@ -439,7 +439,7 @@ InstallMethod( PreImagesSet, function( map, elms ) if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); - elif not IsSubset( Image( map ), elms ) then + elif not IsSubset( Image( map ), elms ) then return fail; fi; return PreImagesSetNC( map, elms ); From cb7672c3b274bdd5365d63b38e1a37e18d9b4ab2 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 13 Jul 2026 22:27:06 +0200 Subject: [PATCH 058/114] Change deprecated RUN_IN_GGMBI to `fail` (#6458) This variable is still set by old versions of the `matgrp` package. By setting the default to `fail`, though, newer `matgrp` versions can detect that it runs in a GAP version where `RUN_IN_GGMBI` is deprecated, and can then instead use the `Run_In_GGMBI` global option. Follow up to PR #6442. --- lib/grpnice.gd | 2 +- tst/testinstall/ggmbi.tst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/grpnice.gd b/lib/grpnice.gd index 8d7dee5536..cb7062fe13 100644 --- a/lib/grpnice.gd +++ b/lib/grpnice.gd @@ -192,7 +192,7 @@ InstallSubsetMaintenance( IsHandledByNiceMonomorphism, # We recommend the (documented) global option `Run_In_GGMBI` # instead of the global variable `RUN_IN_GGMBI`, # but `RUN_IN_GGMBI` is still supported because GAP packages might use it. -RUN_IN_GGMBI:=false; # If somebody would call `GHBI' to make a +RUN_IN_GGMBI:=fail; # If somebody would call `GHBI' to make a # NiceMonomorphism, we would get an infinite recursion. # This flag can be set to avoid GHBIs to be translated # via the niceo. If it is set, the method which does diff --git a/tst/testinstall/ggmbi.tst b/tst/testinstall/ggmbi.tst index ad8465bcfc..801fcf79b8 100644 --- a/tst/testinstall/ggmbi.tst +++ b/tst/testinstall/ggmbi.tst @@ -17,7 +17,7 @@ gap> IsHandledByNiceMonomorphism( G ); true gap> GroupGeneralMappingByImagesNC( G, G, gens, gens );; #I use the global option 'Run_In_GGMBI' not the global variable 'RUN_IN_GGMBI', see '?Run_In_GGMBI' -gap> RUN_IN_GGMBI:= false;; +gap> RUN_IN_GGMBI:= fail;; # - Run some examples where the option gets set, # and where no other tests were available. From 8a364fe4f5b5a78911a8c9286c6044b8c2efb221 Mon Sep 17 00:00:00 2001 From: Thomas Breuer Date: Tue, 14 Jul 2026 13:18:32 +0200 Subject: [PATCH 059/114] Add `ChiefLength` (length of any chief series) (#6455) --- doc/ref/groups.xml | 1 + lib/ctbl.gd | 5 +++++ lib/ctbl.gi | 30 ++++++++++++++++++++++++++++++ lib/grp.gd | 25 +++++++++++++++++++++++++ lib/grp.gi | 24 ++++++++++++++++++++++++ lib/grpnice.gi | 16 ++++++++++++++++ tst/testinstall/ctbl.tst | 40 +++++++++++++++++++++++++++++++++++++++- 7 files changed, 140 insertions(+), 1 deletion(-) diff --git a/doc/ref/groups.xml b/doc/ref/groups.xml index 6638a8b9ad..e44399d007 100644 --- a/doc/ref/groups.xml +++ b/doc/ref/groups.xml @@ -405,6 +405,7 @@ the series without destroying the properties of the series.

<#Include Label="[1]{grp}"> <#Include Label="ChiefSeries"> +<#Include Label="ChiefLength"> <#Include Label="ChiefSeriesThrough"> <#Include Label="ChiefSeriesUnderAction"> <#Include Label="SubnormalSeries"> diff --git a/lib/ctbl.gd b/lib/ctbl.gd index 4254c5c88e..e2d828845b 100644 --- a/lib/ctbl.gd +++ b/lib/ctbl.gd @@ -1083,6 +1083,7 @@ DeclareAttributeSuppCT( "OrdinaryCharacterTable", IsGroup, [] ); ############################################################################# ## #A AbelianInvariants( ) +#A ChiefLength( ) #A CommutatorLength( ) #A Exponent( ) #P IsAbelian( ) @@ -1105,6 +1106,7 @@ DeclareAttributeSuppCT( "OrdinaryCharacterTable", IsGroup, [] ); ## ## Group Operations Applicable to Character Tables ## +## ## ## ## @@ -1139,6 +1141,8 @@ DeclareAttributeSuppCT( "OrdinaryCharacterTable", IsGroup, [] ); ## > CharacterTable( SL( 2, 5 ) ) ];; ## gap> List( tables, AbelianInvariants ); ## [ [ 3 ], [ 2 ], [ ], [ ] ] +## gap> List( tables, ChiefLength ); +## [ 1, 3, 1, 2 ] ## gap> List( tables, CommutatorLength ); ## [ 1, 1, 1, 1 ] ## gap> List( tables, Exponent ); @@ -1192,6 +1196,7 @@ DeclareAttributeSuppCT( "OrdinaryCharacterTable", IsGroup, [] ); ## <#/GAPDoc> ## DeclareAttributeSuppCT( "AbelianInvariants", IsNearlyCharacterTable, [] ); +DeclareAttributeSuppCT( "ChiefLength", IsNearlyCharacterTable, [] ); DeclareAttributeSuppCT( "CommutatorLength", IsNearlyCharacterTable, [] ); DeclareAttributeSuppCT( "Exponent", IsNearlyCharacterTable, [] ); DeclarePropertySuppCT( "IsAbelian", IsNearlyCharacterTable ); diff --git a/lib/ctbl.gi b/lib/ctbl.gi index eb352e0d3f..1122884555 100644 --- a/lib/ctbl.gi +++ b/lib/ctbl.gi @@ -805,6 +805,36 @@ InstallMethod( CharacterDegrees, AttributeMethodByNiceMonomorphism( CharacterDegrees, [ IsGroup ] ); +############################################################################# +## +#F ChiefLength( ) . . . . . . . . . . . . . . . for a character table +## +InstallMethod( ChiefLength, + "for a character table", + [ IsCharacterTable ], + function( tbl ) + local n, prev, N; + + if Size( tbl ) = 1 then + return 0; + elif IsPrimePowerInt( Size( tbl ) ) or IsAbelian( tbl ) then + # Avoid computing all normal subgroups in obvious cases. + return Length( Factors( Size( tbl ) ) ); + fi; + + n:= -1; + prev:= []; + for N in ClassPositionsOfNormalSubgroups( tbl ) do + # The list is sorted according to increasing number of classes. + if IsSubset( N, prev ) then + prev:= N; + n:= n + 1; + fi; + od; + return n; + end ); + + ############################################################################# ## #F CommutatorLength( ) . . . . . . . . . . . . . for a character table diff --git a/lib/grp.gd b/lib/grp.gd index 2a83f80eba..a0e4a8afa0 100644 --- a/lib/grp.gd +++ b/lib/grp.gd @@ -1509,6 +1509,30 @@ DeclareAttribute( "ConjugacyClassesSubgroups", IsGroup ); DeclareAttribute( "LatticeSubgroups", IsGroup ); +############################################################################# +## +#A ChiefLength( ) +## +## <#GAPDoc Label="ChiefLength"> +## +## +## +## +## The chief length of a group is the number of steps in any of its chief +## series, see . +## List( ChiefSeries( g ), Size ); +## [ 24, 12, 4, 1 ] +## gap> ChiefLength( g ); +## 3 +## ]]> +## +## +## <#/GAPDoc> +## +DeclareAttribute( "ChiefLength", IsGroup ); + + ############################################################################# ## #A DerivedLength( ) @@ -1532,6 +1556,7 @@ DeclareAttribute( "LatticeSubgroups", IsGroup ); ## DeclareAttribute( "DerivedLength", IsGroup ); + ############################################################################# ## #A HirschLength( ) diff --git a/lib/grp.gi b/lib/grp.gi index 27f3644271..314a8fe9c1 100644 --- a/lib/grp.gi +++ b/lib/grp.gi @@ -1245,6 +1245,30 @@ end); ## +############################################################################## +## +#M ChiefLength( ) . . . . . . . . . . . . . . . . chief length of a group +## +## For small groups, computing the 'IsSupersolvableGroup' flag is more +## expensive than computing a chief series, +## but the flag helps if it is known. +## +InstallMethod( ChiefLength, + "generic method for groups", + [ IsGroup ], + G -> Length( ChiefSeries( G ) ) - 1 ); + +InstallMethod( ChiefLength, + "for a supersolvable group", + [ IsGroup and IsSupersolvableGroup ], + function( G ) + if Size( G ) = 1 then + return 0; + fi; + return Length( Factors( Size( G ) ) ); + end ); + + ############################################################################## ## #M DerivedLength( ) . . . . . . . . . . . . . . derived length of a group diff --git a/lib/grpnice.gi b/lib/grpnice.gi index 85fadf1555..bef0345638 100644 --- a/lib/grpnice.gi +++ b/lib/grpnice.gi @@ -363,6 +363,22 @@ GroupMethodByNiceMonomorphismCollColl( CoreOp, [ IsGroup, IsGroup ] ); +############################################################################## +## +#M ChiefLength( ) . . . . . . . . . . length of a chief series of a group +## +AttributeMethodByNiceMonomorphism( ChiefLength, + [ IsGroup ] ); + + +############################################################################## +## +#M CommutatorLength( ) . . . . . . . . . . commutator length of a group +## +AttributeMethodByNiceMonomorphism( CommutatorLength, + [ IsGroup ] ); + + ############################################################################## ## #M DerivedLength( ) . . . . . . . . . . . . . . derived length of a group diff --git a/tst/testinstall/ctbl.tst b/tst/testinstall/ctbl.tst index 3f5ec76722..824a0868b1 100644 --- a/tst/testinstall/ctbl.tst +++ b/tst/testinstall/ctbl.tst @@ -1,6 +1,10 @@ -#@local g,t,lin,G +#@local g,t,lin,G,attr gap> START_TEST("ctbl.tst"); +# Reset the counter of automatically assigned identifiers, +# in order to admit reading this file several times in a GAP session. +gap> LARGEST_IDENTIFIER_NUMBER[1]:= 0;; + # `ClassPositionsOf...' for the trivial group (which usually causes trouble) gap> g:= TrivialGroup( IsPermGroup );; gap> t:= CharacterTable( g );; @@ -460,5 +464,39 @@ gap> IrrDixonSchneider( G );; Irr( G );; gap> InfoText( OrdinaryCharacterTable( G ) ); "origin: Dixon's Algorithm" +# group attributes for character tables +gap> for G in [ TrivialGroup(), CyclicGroup( 5 ), DihedralGroup( 12 ), +> SymmetricGroup( 4 ), AlternatingGroup( 6 ), SL( 2, 5 ) ] do +> t:= CharacterTable( G ); +> for attr in [ +> AbelianInvariants, +> ChiefLength, +> CommutatorLength, +> Exponent, +> IsAbelian, +> IsAlmostSimple, +> IsCyclic, +> IsElementaryAbelian, +> IsFinite, +> IsMonomial, +> IsNilpotent, +> IsPerfect, +> IsQuasisimple, +> IsSimple, +> IsSporadicSimple, +> IsSupersolvable, +> NrConjugacyClasses, +> Size, +> ] do +> if attr( G ) <> attr( t ) then +> Error( "difference for '", attr, "'" ); +> fi; +> od; +> if IsSimple( G ) and IsomorphismTypeInfoFiniteSimpleGroup( G ) <> +> IsomorphismTypeInfoFiniteSimpleGroup( t ) then +> Error( "difference for '", IsomorphismTypeInfoFiniteSimpleGroup, "'" ); +> fi; +> od; + ## gap> STOP_TEST( "ctbl.tst" ); From 181f4890cae54dce4a9a21ccff76588e51f6ab0b Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 20 May 2026 09:13:46 +0100 Subject: [PATCH 060/114] re-edited library files, adding NC --- lib/mapping.gd | 2 +- lib/mapping.gi | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/lib/mapping.gd b/lib/mapping.gd index 4feb438311..1170112847 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -977,7 +977,7 @@ DeclareGlobalFunction( "Images" ); ## ## ## If elm is an element of the range of the general mapping -## map then returns the set of all +## map then returns the set of all ## preimages of elm under map. ##

## From &GAP; version 4.16.1 diff --git a/lib/mapping.gi b/lib/mapping.gi index d428e11275..bd1c572ecc 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -333,8 +333,6 @@ InstallGlobalFunction( PreImagesNC, function ( arg ) # preimage of the empty list elif IsList( img ) and IsEmpty( img ) then - return []; - fi; fi; ErrorNoReturn( "usage: PreImagesNC(), PreImagesNC(,), ", @@ -1202,6 +1200,33 @@ InstallMethod( PreImagesSetNC, return primgs; end ); + +InstallMethod( PreImagesSet, + "for general mapping, and finite collection", + CollFamRangeEqFamElms, + [ IsGeneralMapping, IsCollection ], 0, + function( map, elms ) + local im, elm; + if not IsFinite( elms ) then + TryNextMethod(); + fi; + im:= Image( map ); + for elm in Enumerator( elms ) do + if not (elm in im ) then + return []; + fi; + od; + return PreImagesSetNC( map, elms ); + end ); + +InstallMethod( PreImagesSetNC, + "for general mapping, and empty list", + true, + [ IsGeneralMapping, IsList and IsEmpty ], 0, + function( map, elms ) + return []; + end ); + InstallMethod( PreImagesSet, "for general mapping, and finite collection", CollFamRangeEqFamElms, @@ -1228,7 +1253,7 @@ InstallMethod( PreImagesSet, true, [ IsGeneralMapping, IsList and IsEmpty ], 0, function( map, elms ) - return []; + return []; end ); @@ -1282,6 +1307,14 @@ InstallMethod( PreImagesRepresentativeNC, Error( "no default method for s.p. general mapping" ); end ); +InstallMethod( PreImagesRepresentativeNC, + "for s.p. general mapping, and element", + FamRangeEqFamElm, + [ IsSPGeneralMapping, IsObject ], 0, + function( map, elm ) + Error( "no default method for s.p. general mapping" ); + end ); + ############################################################################# ## From 94a8ca6075d3bb79602c9ff926db361529721630 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 8 Jun 2026 11:15:49 +0200 Subject: [PATCH 061/114] kernel: improve `ErrorReturnVoid` break-loop message (#6416) ... and in general make its phrasing more consistent. Also update some several outdated sections of the documentation about break loops and error handling. Co-authored-by: Codex --- doc/ref/mloop.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/ref/mloop.xml b/doc/ref/mloop.xml index 8b9aef83fa..2f8831aaf6 100644 --- a/doc/ref/mloop.xml +++ b/doc/ref/mloop.xml @@ -1,4 +1,5 @@ - + @@ -477,6 +478,7 @@ indicate that you are in a break loop. 1/0; Error, Rational operations: must not be zero +Stack trace: not in any function at *stdin*:2 you can enter 'quit;' to quit to outer loop ]]> From 3c72620b779f311939882e11f4d73e7b5027d920 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 9 Jun 2026 01:07:41 +0200 Subject: [PATCH 062/114] Adjust when 'Stack trace:' message is printed (#6432) * Adjust when 'Stack trace:' message is printed * Update one more error message * Add two missing 'Stack trace:' --- doc/ref/mloop.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/ref/mloop.xml b/doc/ref/mloop.xml index 2f8831aaf6..4f0ff1dda2 100644 --- a/doc/ref/mloop.xml +++ b/doc/ref/mloop.xml @@ -478,7 +478,6 @@ indicate that you are in a break loop. 1/0; Error, Rational operations: must not be zero -Stack trace: not in any function at *stdin*:2 you can enter 'quit;' to quit to outer loop ]]> From 5ed2b08a5d5d32f124022068fde0426266a6bbc7 Mon Sep 17 00:00:00 2001 From: Thomas Breuer Date: Wed, 1 Jul 2026 15:18:55 +0200 Subject: [PATCH 063/114] turn the global variable `RUN_IN_GGMBI` into a global option `Run_In_GGMBI` (#6442) --- lib/grpnice.gd | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/grpnice.gd b/lib/grpnice.gd index cb7062fe13..c83d098f13 100644 --- a/lib/grpnice.gd +++ b/lib/grpnice.gd @@ -193,6 +193,7 @@ InstallSubsetMaintenance( IsHandledByNiceMonomorphism, # instead of the global variable `RUN_IN_GGMBI`, # but `RUN_IN_GGMBI` is still supported because GAP packages might use it. RUN_IN_GGMBI:=fail; # If somebody would call `GHBI' to make a +`Run_In_GGMBI` (#6442)) # NiceMonomorphism, we would get an infinite recursion. # This flag can be set to avoid GHBIs to be translated # via the niceo. If it is set, the method which does From 5bd2601316981cb1881d8b61c73a3d201b7b5ec7 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 9 Jul 2026 15:53:59 +0100 Subject: [PATCH 064/114] adjusted the documentation in 32.5 --- lib/mapping.gd | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/lib/mapping.gd b/lib/mapping.gd index 1170112847..c7523d453f 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -982,14 +982,14 @@ DeclareGlobalFunction( "Images" ); ##

## From &GAP; version 4.16.1 ## PreImagesElm was renamed PreImagesElmNC -## throughout the library, and PreImagesElm now checks that +## throughout the library, and the new PreImagesElm checks that ## elm is an element of the image before calling PreImagesElmNC. -## If elm is not in the range then an error is thrown. ## If elm is in the range but not in the image then fail ## is returned. +## If elm is not even in the range then an error is signalled. ##

## When using PreImagesElmNC anything may happen if elm -## is not an element of the range of map. +## is not an element of the image of map. ##

## ## @@ -1013,7 +1013,7 @@ DeclareOperation( "PreImagesElmNC", [ IsGeneralMapping, IsObject ] ); ## returns the unique preimage of elm under ## map. ##

-## Anything may happen if elm is not an element of the range of +## Anything may happen if elm is not an element of the image of ## map. ## ## @@ -1034,19 +1034,17 @@ DeclareOperation( "PreImageElm", ## ## ## -## If elm is an element of the range of the general mapping -## map then returns either a -## representative of the set of preimages of elm under map or -## fail, the latter if and only if elm -## has no preimages under map. +## If elm is an element of the image of the general mapping +## map then returns a +## representative of the set of preimages of elm under map. ##

## From &GAP; version 4.16.1 PreImagesRepresentative ## was renamed PreImagesRepresentativeNC throughout the library, -## and PreImagesRepresentative now checks that elm is an +## and the new PreImagesRepresentative checks that elm is an ## element of the image before calling PreImagesRepresentativeNC. -## If elm is not in the range then an error is thrown. ## If elm is in the range but not in the image then fail ## is returned. +## If elm is not even in the range then an error is signalled. ##

## When using PreImagesRepresentativeNC anything may happen if ## elm is not an element of the range of map. @@ -1070,20 +1068,21 @@ DeclareOperation( "PreImagesRepresentativeNC", [ IsGeneralMapping, IsObject ] ); ## ## ## -## If elms is a subset of the range of the general mapping map +## If elms is a subset of the image of the general mapping map ## then returns the set of all preimages of ## elms under map. ##

## From &GAP; version 4.16.1 PreImagesSet ## has been renamed PreImagesSetNC throughout the library, -## and PreImagesSet now checks that elms is a +## and the new PreImagesSet checks that elms is a ## subset of the image before calling PreImagesSetNC. -## If elms is not a subset of the range then an error is thrown. ## If elm is a subset the range but not a subset of the image then ## fail is returned. +## (Mathematically, this is not correct.) +## If elms is not a subset of the range then an error is signalled. ##

## When using PreImagesSetNC anything may happen if elms -## is not a subset of the range of map. +## is not a subset of the image of map. ##

## ## @@ -1140,7 +1139,7 @@ DeclareOperation( "PreImagesSetNC", [ IsGeneralMapping, IsListOrCollection ] ); ## and to resp. when ## called with two arguments. ##

-## If the second argument is not an element or a subset of the range of +## If the second argument is not an element or a subset of the image of ## the first argument, an error is signalled. ## ## @@ -1200,15 +1199,15 @@ DeclareGlobalFunction( "PreImage" ); ##

## From &GAP; version 4.16.1 PreImages ## has been renamed PreImagesNC throughout the library, -## and PreImages now checks that elm or coll +## and the new PreImages checks that elm or coll ## belong to the image before calling PreImagesNC. -## If elm or coll are not contained in the range -## then an error is thrown. ## If elm or coll are contained in the range but not in the ## image then fail is returned. +## If elm or coll are not contained in the range +## then an error is signalled. ##

## When using PreImagesNC anything may happen if elm -## or coll do not belong to the range of map. +## or coll do not belong to the image of map. ##

## ## From 93ab53724c8cd4a6b20fd419ceba679cff4f7300 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 15 Jul 2026 17:24:58 +0100 Subject: [PATCH 065/114] using Intersection(elms,Range(map)) in PreImagesSet --- lib/field.gi | 4 +--- lib/fldabnum.gi | 4 +--- lib/ghom.gi | 4 +--- lib/ghomfp.gi | 4 +--- lib/ghomperm.gi | 12 +++--------- lib/grpnice.gd | 1 - lib/mapphomo.gi | 24 ++++++------------------ lib/mapping.gi | 34 +++++++++++++++++++++------------- lib/mapprep.gi | 22 ++++++---------------- 9 files changed, 40 insertions(+), 69 deletions(-) diff --git a/lib/field.gi b/lib/field.gi index 3788b0be02..dfedafa1b4 100644 --- a/lib/field.gi +++ b/lib/field.gi @@ -1368,8 +1368,6 @@ InstallMethod( PreImagesSet, function ( hom, elms ) if not IsSubset( Range(hom), elms ) then Error( " is not a subset of the range of " ); - elif not IsSubset( Image(hom), elms ) then - return fail; fi; - return PreImagesSetNC( hom, elms ); + return PreImagesSetNC( hom, Intersection( elms, Range( hom ) ) ); end ); diff --git a/lib/fldabnum.gi b/lib/fldabnum.gi index fcd3524119..b6c403b862 100644 --- a/lib/fldabnum.gi +++ b/lib/fldabnum.gi @@ -1963,10 +1963,8 @@ InstallMethod( PreImagesSet, function ( aut, F ) if not IsSubset( Range(aut), F ) then Error( " is not a subset of the range of mapping " ); - elif not IsSubset( Image(aut), F ) then - return fail; fi; - return PreImagesSetNC( aut, F ); + return PreImagesSetNC( aut, Intersection( F, Range( aut ) ) ); end ); ############################################################################# diff --git a/lib/ghom.gi b/lib/ghom.gi index 175e6691e1..f8576a4d68 100644 --- a/lib/ghom.gi +++ b/lib/ghom.gi @@ -1297,10 +1297,8 @@ InstallMethod( PreImagesSet, function( hom, U ) if not IsSubset( Range( hom ), U ) then Error( " is not a subset of the range of mapping " ); - elif not IsSubset( Image( hom ), U ) then - return fail; fi; - return PreImagesSetNC( hom, U ); + return PreImagesSetNC( hom, Intersection( U, Range( hom ) ) ); end ); diff --git a/lib/ghomfp.gi b/lib/ghomfp.gi index df5689705b..b4e7ad613b 100644 --- a/lib/ghomfp.gi +++ b/lib/ghomfp.gi @@ -631,10 +631,8 @@ InstallMethod( PreImagesSet, "map from (sub)group of fp group", function(hom,u) if not IsSubset( Range(hom), u ) then Error( " is not a subset of the range of " ); - elif not IsSubset( Image(hom), u ) then - return fail; fi; - return PreImagesSetNC(hom,u); + return PreImagesSetNC( hom, Intersection( u, Range(hom) ) ); end); diff --git a/lib/ghomperm.gi b/lib/ghomperm.gi index 1ee763a714..e2eb4f97bf 100644 --- a/lib/ghomperm.gi +++ b/lib/ghomperm.gi @@ -86,10 +86,8 @@ InstallMethod( PreImagesSet, function( map, elms ) if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); - elif not IsSubset( Image( map ), elms ) then - return fail; fi; - return PreImagesSetNC( map, elms ); + return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); end ); ############################################################################# @@ -1655,10 +1653,8 @@ InstallMethod( PreImagesSet, "constituent homomorphism",CollFamRangeEqFamElms, function( hom, I ) if not IsSubset( Range( hom ), I ) then Error( " is not a subset of the range of mapping " ); - elif not IsSubset( Image( hom ), I ) then - return fail; fi; - return PreImagesSetNC( hom, I ); + return PreImagesSetNC( hom, Intersection( I, Range( hom ) ) ); end ); ############################################################################# @@ -1950,10 +1946,8 @@ InstallMethod( PreImagesSet, CollFamRangeEqFamElms, function( hom, I ) if not IsSubset( Range( hom ), I ) then Error( " is not a subset of the range of mapping " ); - elif not IsSubset( Image( hom ), I ) then - return fail; fi; - return PreImagesSetNC( hom, I ); + return PreImagesSetNC( hom, Intersection( I, Range( hom ) ) ); end ); ############################################################################# diff --git a/lib/grpnice.gd b/lib/grpnice.gd index c83d098f13..cb7062fe13 100644 --- a/lib/grpnice.gd +++ b/lib/grpnice.gd @@ -193,7 +193,6 @@ InstallSubsetMaintenance( IsHandledByNiceMonomorphism, # instead of the global variable `RUN_IN_GGMBI`, # but `RUN_IN_GGMBI` is still supported because GAP packages might use it. RUN_IN_GGMBI:=fail; # If somebody would call `GHBI' to make a -`Run_In_GGMBI` (#6442)) # NiceMonomorphism, we would get an infinite recursion. # This flag can be set to avoid GHBIs to be translated # via the niceo. If it is set, the method which does diff --git a/lib/mapphomo.gi b/lib/mapphomo.gi index 566b5d6af5..8a19af90ee 100644 --- a/lib/mapphomo.gi +++ b/lib/mapphomo.gi @@ -407,10 +407,8 @@ InstallMethod( PreImagesSet, function( map, elms ) if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); - elif not IsSubset( Image( map ), elms ) then - return fail; fi; - return PreImagesSetNC( map, elms ); + return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); end ); @@ -439,10 +437,8 @@ InstallMethod( PreImagesSet, function( map, elms ) if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); - elif not IsSubset( Image( map ), elms ) then - return fail; fi; - return PreImagesSetNC( map, elms ); + return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); end ); @@ -794,10 +790,8 @@ InstallMethod( PreImagesSet, function( map, elms ) if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); - elif not IsSubset( Image( map ), elms ) then - return fail; fi; - return PreImagesSetNC( map, elms ); + return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); end ); @@ -995,10 +989,8 @@ InstallMethod( PreImagesSet, function( map, elms ) if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); - elif not IsSubset( Image( map ), elms ) then - return fail; fi; - return PreImagesSetNC( map, elms ); + return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); end ); @@ -1105,10 +1097,8 @@ InstallMethod( PreImagesSet, function( map, elms ) if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); - elif not IsSubset( Image( map ), elms ) then - return fail; fi; - return PreImagesSetNC( map, elms ); + return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); end ); @@ -1148,10 +1138,8 @@ InstallMethod( PreImagesSet, function( map, elms ) if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); - elif not IsSubset( Image( map ), elms ) then - return fail; fi; - return PreImagesSetNC( map, elms ); + return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); end ); diff --git a/lib/mapping.gi b/lib/mapping.gi index bd1c572ecc..651bfda39c 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -239,7 +239,8 @@ end ); InstallGlobalFunction( PreImage, function ( arg ) local map, # gen. mapping , first argument - img; # element , second argument + img, # element , second argument + rng; # the range of map if Length( arg ) > 0 and not IsGeneralMapping( arg[1] ) then ErrorNoReturn( " must be a general mapping" ); @@ -254,28 +255,29 @@ InstallGlobalFunction( PreImage, function ( arg ) map := arg[1]; img := arg[2]; + rng := Range( map ); # preimage of a single element under if FamRangeEqFamElm( FamilyObj( map ), FamilyObj( img ) ) then if not ( IsInjective( map ) and IsSurjective( map ) ) then ErrorNoReturn( " must be an injective and surjective ", "mapping" ); - elif not img in Range( map ) then + elif not img in rng then ErrorNoReturn( " must be an element of Range()" ); fi; return PreImageElm( map, img ); # preimage of a collection of elements under elif CollFamRangeEqFamElms( FamilyObj( map ), FamilyObj( img ) ) then - if not IsSubset( Range( map ), img ) then + if not IsSubset( rng, img ) then ErrorNoReturn( "the collection must be contained in ", "Range()" ); fi; if IsDomain( img ) or IsSSortedList( img ) then - return PreImagesSetNC( map, img ); + return PreImagesSetNC( map, Intersection( img, rng ) ); elif IsHomogeneousList( img ) then - return PreImagesSetNC( map, Set( img ) ); + return PreImagesSetNC( map, Intersection( Set( img ), rng ) ); fi; # preimage of the empty list @@ -342,7 +344,12 @@ end ); InstallGlobalFunction( PreImages, function ( arg ) local map, # mapping , first argument - img; # element , second argument + img, # element , second argument + rng; # the range of map + + if Length( arg ) > 0 and not IsGeneralMapping( arg[1] ) then + ErrorNoReturn( " must be a general mapping" ); + fi; # preimage of the range under if Length( arg ) = 1 then @@ -353,6 +360,7 @@ InstallGlobalFunction( PreImages, function ( arg ) map := arg[1]; img := arg[2]; + rng := Range( map ); if not IsGeneralMapping( map ) then ErrorNoReturn( " must be a general mapping" ); @@ -360,22 +368,22 @@ InstallGlobalFunction( PreImages, function ( arg ) # preimage of a single element under if FamRangeEqFamElm( FamilyObj( map ), FamilyObj( img ) ) then - if not img in Range( map ) then + if not img in rng then ErrorNoReturn( " must be an element of Range()" ); fi; return PreImagesElm( map, img ); # preimage of a collection of elements under elif CollFamRangeEqFamElms( FamilyObj( map ), FamilyObj( img ) ) then - if not IsSubset( Range( map ), img ) then + if not IsSubset( rng, img ) then ErrorNoReturn( "the collection must be contained in ", "Range()" ); fi; if IsDomain( img ) or IsSSortedList( img ) then - return PreImagesSet( map, img ); + return PreImagesSetNC( map, Intersection( img, rng ) ); elif IsHomogeneousList( img ) then - return PreImagesSet( map, Set( img ) ); + return PreImagesSet( map, Intersection( Set( img ), rng ) ); fi; # preimage of the empty list @@ -1232,12 +1240,12 @@ InstallMethod( PreImagesSet, CollFamRangeEqFamElms, [ IsGeneralMapping, IsCollection ], 0, function( map, elms ) + local inter; if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); - elif not IsSubset( Image( map ), elms ) then - return fail; fi; - return PreImagesSetNC( map, elms ); + inter := Intersection( elms, Image( map ) ); + return PreImagesSetNC( map, inter ); end ); InstallMethod( PreImagesSetNC, diff --git a/lib/mapprep.gi b/lib/mapprep.gi index 07ba28d9b1..1aa6f8f829 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -313,7 +313,7 @@ InstallMethod( PreImagesElmNC, local im; im:= PreImagesElmNC( com!.map2, elm ); if not IsEmpty( im ) then - return PreImagesSetNC( com!.map1, im ); + return PreImagesSetNC( com!.map1, im ); ## why Set and not Elm here ?? else return []; fi; @@ -359,10 +359,8 @@ InstallMethod( PreImagesSet, function( com, elms ) if not IsSubset( Range(com), elms ) then Error( " is not a subset of the range of mapping " ); - elif not IsSubset( Image(com), elms ) then - return fail; fi; - return PreImagesSetNC( com, elms ); + return PreImagesSetNC( com, Intersection( elms, Range( com ) ) ); end ); @@ -1183,10 +1181,8 @@ InstallMethod( PreImagesSet, function ( inv, elms ) if not IsSubset( Range(inv), elms ) then Error( " is not a subset of the range of mapping " ); - elif not IsSubset( Image(inv), elms ) then - return fail; fi; - return PreImagesSetNC( inv, elms ); + return PreImagesSetNC( inv, Intersection( elms, Range( inv ) ) ); end ); @@ -1468,10 +1464,8 @@ InstallMethod( PreImagesSet, function ( id, elms ) if not IsSubset( Range(id), elms ) then Error( " is not a subset of the range of mapping " ); - elif not IsSubset( Image(id), elms ) then - return fail; fi; - return PreImagesSetNC( id, elms ); + return PreImagesSetNC( id, Intersection( elms, Range( id ) ) ); end ); @@ -1804,10 +1798,8 @@ InstallMethod( PreImagesSet, function( zero, elms ) if not IsSubset( Range(zero), elms ) then Error( " is not a subset of the range of mapping " ); - elif not IsSubset( Image(zero), elms ) then - return fail; fi; - return PreImagesSetNC( zero, elms ); + return PreImagesSetNC( zero, Intersection( elms, Range( zero ) ) ); end ); @@ -2086,10 +2078,8 @@ InstallMethod( PreImagesSet, function( res, elms ) if not IsSubset( Range(res), elms ) then Error( " is not a subset of the range of mapping " ); - elif not IsSubset( Image(res), elms ) then - return fail; fi; - return PreImagesSetNC( res, elms ); + return PreImagesSetNC( res, Intersection( elms, Range( res ) ) ); end ); From 510aae3b4f83aa3fc320479ec955b7ceaacf3a9e Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 15 Jul 2026 19:23:14 +0100 Subject: [PATCH 066/114] addition to tst/testinstall/mapphomo.tst --- tst/testinstall/mapphomo.tst | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tst/testinstall/mapphomo.tst b/tst/testinstall/mapphomo.tst index d6468f7834..c40f912cba 100644 --- a/tst/testinstall/mapphomo.tst +++ b/tst/testinstall/mapphomo.tst @@ -91,5 +91,32 @@ gap> for G in [ SymmetricGroup(5), DihedralGroup(8), GL(2,3) ] do > PreImagesRepresentative( hom, G.1 ); > od; +# Check PreImages... now that NC versions have been added +gap> gens := [ (1,2,3,4), (1,2,3) ];; +gap> G := Group( gens );; +gap> H := Group( [ (4,5,6,7,8,9), (5,9)(6,8) ] );; +gap> imgs := [ (5,9)(6,8), (4,6,8)(5,7,9) ];; +gap> hom := GroupHomomorphismByImages( G, H, gens, imgs );; +gap> PreImagesSet( hom, [ (4,6)(7,9) ] ); +[ (2,3), (1,2,4,3), (1,3,4,2), (1,4) ] +gap> PreImagesSet( hom, [ (4,5,6,7,8,9) ] ); +[ ] +gap> PreImagesSet( hom, [ (4,6)(7,9), (4,5,6,7,8,9) ] ); +[ (2,3), (1,2,4,3), (1,3,4,2), (1,4) ] +gap> PreImagesSet( hom, [ (7,8,9) ] ); +Error, is not a subset of the range of +gap> PreImagesElm( hom, (4,6)(7,9) ); +RightCoset(Group([ (1,4)(2,3), (1,2)(3,4) ]),(1,2,4,3)) +gap> PreImagesRepresentative( hom, (4,6)(7,9) ); +(1,2,4,3) +gap> PreImagesElm( hom, (4,5,6,7,8,9) ); +fail +gap> PreImagesRepresentative( hom, (4,5,6,7,8,9) ); +fail +gap> PreImagesElm( hom, (7,8,9) ); +Error, is not in the range of +gap> PreImagesRepresentative( hom, (7,8,9) ); +Error, is not in the range of mapping + # gap> STOP_TEST( "mapphomo.tst" ); From 4348a341b0d3ae2a84dc59bbdfa469efe26727de Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 15 Jul 2026 19:29:38 +0100 Subject: [PATCH 067/114] using Intersection(elms,Range(map)) in PreImagesSet --- lib/mapping.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapping.gd b/lib/mapping.gd index c7523d453f..8265fa7685 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -977,7 +977,7 @@ DeclareGlobalFunction( "Images" ); ## ## ## If elm is an element of the range of the general mapping -## map then returns the set of all +## map then returns the set of all ## preimages of elm under map. ##

## From &GAP; version 4.16.1 From 8dcf46e3ebebcf3bff29825a46b9dd40081762bd Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 15 Jul 2026 19:40:02 +0100 Subject: [PATCH 068/114] revise the documentation for PreImagesSet --- lib/mapping.gd | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/mapping.gd b/lib/mapping.gd index 8265fa7685..dc6c27a705 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -1075,14 +1075,13 @@ DeclareOperation( "PreImagesRepresentativeNC", [ IsGeneralMapping, IsObject ] ); ## From &GAP; version 4.16.1 PreImagesSet ## has been renamed PreImagesSetNC throughout the library, ## and the new PreImagesSet checks that elms is a -## subset of the image before calling PreImagesSetNC. +## subset of the range before calling PreImagesSetNC. ## If elm is a subset the range but not a subset of the image then -## fail is returned. -## (Mathematically, this is not correct.) +## PreImagesSetNC( map, Intersection( elms, Range(map) ) is returned. ## If elms is not a subset of the range then an error is signalled. ##

## When using PreImagesSetNC anything may happen if elms -## is not a subset of the image of map. +## is not a subset of the range of map. ##

## ## From aa5a67cc252f5a9f47dd8d04a120c8030658ae14 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 15 Jul 2026 19:47:55 +0100 Subject: [PATCH 069/114] revise the documentation for PreImagesSet --- lib/mapping.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapping.gd b/lib/mapping.gd index dc6c27a705..c3385a81f7 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -1068,7 +1068,7 @@ DeclareOperation( "PreImagesRepresentativeNC", [ IsGeneralMapping, IsObject ] ); ## ## ## -## If elms is a subset of the image of the general mapping map +## If elms is a subset of the range of the general mapping map ## then returns the set of all preimages of ## elms under map. ##

From 5e7c1cf5a69b6a1940869dac9d75569d529ab8f2 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:44:27 +0100 Subject: [PATCH 070/114] Update lib/field.gi Co-authored-by: Thomas Breuer --- lib/field.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/field.gi b/lib/field.gi index dfedafa1b4..2ba45207ce 100644 --- a/lib/field.gi +++ b/lib/field.gi @@ -1369,5 +1369,5 @@ InstallMethod( PreImagesSet, if not IsSubset( Range(hom), elms ) then Error( " is not a subset of the range of " ); fi; - return PreImagesSetNC( hom, Intersection( elms, Range( hom ) ) ); + return PreImagesSetNC( hom, Intersection( elms, Image( hom ) ) ); end ); From 866331f33f6bc59717be4851eefd4eb401e41b95 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:44:48 +0100 Subject: [PATCH 071/114] Update lib/fldabnum.gi Co-authored-by: Thomas Breuer --- lib/fldabnum.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fldabnum.gi b/lib/fldabnum.gi index b6c403b862..333cf239bb 100644 --- a/lib/fldabnum.gi +++ b/lib/fldabnum.gi @@ -1964,7 +1964,7 @@ InstallMethod( PreImagesSet, if not IsSubset( Range(aut), F ) then Error( " is not a subset of the range of mapping " ); fi; - return PreImagesSetNC( aut, Intersection( F, Range( aut ) ) ); + return PreImagesSetNC( aut, Intersection( F, Image( aut ) ) ); end ); ############################################################################# From bdab1a86dcd3dc51c3d4cb5589931d961354a990 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:45:03 +0100 Subject: [PATCH 072/114] Update lib/ghom.gi Co-authored-by: Thomas Breuer --- lib/ghom.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ghom.gi b/lib/ghom.gi index f8576a4d68..be5d1e1ad5 100644 --- a/lib/ghom.gi +++ b/lib/ghom.gi @@ -1298,7 +1298,7 @@ function( hom, U ) if not IsSubset( Range( hom ), U ) then Error( " is not a subset of the range of mapping " ); fi; - return PreImagesSetNC( hom, Intersection( U, Range( hom ) ) ); + return PreImagesSetNC( hom, Intersection( U, Image( hom ) ) ); end ); From 0fadf6434600ec91da996c39fb082fcc50365a32 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:45:16 +0100 Subject: [PATCH 073/114] Update lib/ghomfp.gi Co-authored-by: Thomas Breuer --- lib/ghomfp.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ghomfp.gi b/lib/ghomfp.gi index b4e7ad613b..7c2f3d4d0c 100644 --- a/lib/ghomfp.gi +++ b/lib/ghomfp.gi @@ -632,7 +632,7 @@ function(hom,u) if not IsSubset( Range(hom), u ) then Error( " is not a subset of the range of " ); fi; - return PreImagesSetNC( hom, Intersection( u, Range(hom) ) ); + return PreImagesSetNC( hom, Intersection( u, Image(hom) ) ); end); From 425e88fe35dfab4f4925a471c9526f7a21b00735 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:45:27 +0100 Subject: [PATCH 074/114] Update lib/ghomperm.gi Co-authored-by: Thomas Breuer --- lib/ghomperm.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ghomperm.gi b/lib/ghomperm.gi index e2eb4f97bf..7aa753ec89 100644 --- a/lib/ghomperm.gi +++ b/lib/ghomperm.gi @@ -87,7 +87,7 @@ function( map, elms ) if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); fi; - return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); + return PreImagesSetNC( map, Intersection( elms, Image( map ) ) ); end ); ############################################################################# From 208dbcf60270806d2ea2cd5aa67a4fe87a44855b Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:45:44 +0100 Subject: [PATCH 075/114] Update lib/mapprep.gi Co-authored-by: Thomas Breuer --- lib/mapprep.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapprep.gi b/lib/mapprep.gi index 1aa6f8f829..6123f7985d 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -360,7 +360,7 @@ InstallMethod( PreImagesSet, if not IsSubset( Range(com), elms ) then Error( " is not a subset of the range of mapping " ); fi; - return PreImagesSetNC( com, Intersection( elms, Range( com ) ) ); + return PreImagesSetNC( com, Intersection( elms, Image( com ) ) ); end ); From c187191c3cc0ddcb58fe3faa1d72924a4a0f5832 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:45:55 +0100 Subject: [PATCH 076/114] Update lib/mapprep.gi Co-authored-by: Thomas Breuer --- lib/mapprep.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapprep.gi b/lib/mapprep.gi index 6123f7985d..ed6ae0057b 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -1182,7 +1182,7 @@ InstallMethod( PreImagesSet, if not IsSubset( Range(inv), elms ) then Error( " is not a subset of the range of mapping " ); fi; - return PreImagesSetNC( inv, Intersection( elms, Range( inv ) ) ); + return PreImagesSetNC( inv, Intersection( elms, Image( inv ) ) ); end ); From 6b4094827f654ce46bc6178fc04ed2e66f46da6d Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:46:11 +0100 Subject: [PATCH 077/114] Update lib/mapprep.gi Co-authored-by: Thomas Breuer --- lib/mapprep.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapprep.gi b/lib/mapprep.gi index ed6ae0057b..ea89ce1487 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -1465,7 +1465,7 @@ InstallMethod( PreImagesSet, if not IsSubset( Range(id), elms ) then Error( " is not a subset of the range of mapping " ); fi; - return PreImagesSetNC( id, Intersection( elms, Range( id ) ) ); + return PreImagesSetNC( id, Intersection( elms, Image( id ) ) ); end ); From 58b8c93aed73649f9c07855b33f367d79b6256ec Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:46:20 +0100 Subject: [PATCH 078/114] Update lib/mapprep.gi Co-authored-by: Thomas Breuer --- lib/mapprep.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapprep.gi b/lib/mapprep.gi index ea89ce1487..f2acedf2b0 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -1799,7 +1799,7 @@ InstallMethod( PreImagesSet, if not IsSubset( Range(zero), elms ) then Error( " is not a subset of the range of mapping " ); fi; - return PreImagesSetNC( zero, Intersection( elms, Range( zero ) ) ); + return PreImagesSetNC( zero, Intersection( elms, Image( zero ) ) ); end ); From a84b430ccc74bd585c7a575d8b80b9e20bd82375 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:46:35 +0100 Subject: [PATCH 079/114] Update lib/mapprep.gi Co-authored-by: Thomas Breuer --- lib/mapprep.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapprep.gi b/lib/mapprep.gi index f2acedf2b0..a72a05bd34 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -2079,7 +2079,7 @@ InstallMethod( PreImagesSet, if not IsSubset( Range(res), elms ) then Error( " is not a subset of the range of mapping " ); fi; - return PreImagesSetNC( res, Intersection( elms, Range( res ) ) ); + return PreImagesSetNC( res, Intersection( elms, Image( res ) ) ); end ); From 5df23f7ab073dde72697e41eeb5818bb693636a0 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:47:31 +0100 Subject: [PATCH 080/114] Update lib/ghomperm.gi Co-authored-by: Thomas Breuer --- lib/ghomperm.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ghomperm.gi b/lib/ghomperm.gi index 7aa753ec89..0f698408e4 100644 --- a/lib/ghomperm.gi +++ b/lib/ghomperm.gi @@ -1654,7 +1654,7 @@ InstallMethod( PreImagesSet, "constituent homomorphism",CollFamRangeEqFamElms, if not IsSubset( Range( hom ), I ) then Error( " is not a subset of the range of mapping " ); fi; - return PreImagesSetNC( hom, Intersection( I, Range( hom ) ) ); + return PreImagesSetNC( hom, Intersection( I, Image( hom ) ) ); end ); ############################################################################# From 76b5357fd5677eed74accad4b2f81ee787cbe2ec Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:47:59 +0100 Subject: [PATCH 081/114] Update lib/ghomperm.gi Co-authored-by: Thomas Breuer --- lib/ghomperm.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ghomperm.gi b/lib/ghomperm.gi index 0f698408e4..de0af5f7e3 100644 --- a/lib/ghomperm.gi +++ b/lib/ghomperm.gi @@ -1947,7 +1947,7 @@ InstallMethod( PreImagesSet, CollFamRangeEqFamElms, if not IsSubset( Range( hom ), I ) then Error( " is not a subset of the range of mapping " ); fi; - return PreImagesSetNC( hom, Intersection( I, Range( hom ) ) ); + return PreImagesSetNC( hom, Intersection( I, Image( hom ) ) ); end ); ############################################################################# From d60080439f45d916cd959fae0b66e0b1ba0921c7 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:48:24 +0100 Subject: [PATCH 082/114] Update lib/mapphomo.gi Co-authored-by: Thomas Breuer --- lib/mapphomo.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapphomo.gi b/lib/mapphomo.gi index 8a19af90ee..6503dc323a 100644 --- a/lib/mapphomo.gi +++ b/lib/mapphomo.gi @@ -408,7 +408,7 @@ InstallMethod( PreImagesSet, if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); fi; - return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); + return PreImagesSetNC( map, Intersection( elms, Image( map ) ) ); end ); From ed90c7a8488732287ad57a5a5c3dccc2deb0b305 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:48:44 +0100 Subject: [PATCH 083/114] Update lib/mapphomo.gi Co-authored-by: Thomas Breuer --- lib/mapphomo.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapphomo.gi b/lib/mapphomo.gi index 6503dc323a..01717d8122 100644 --- a/lib/mapphomo.gi +++ b/lib/mapphomo.gi @@ -438,7 +438,7 @@ InstallMethod( PreImagesSet, if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); fi; - return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); + return PreImagesSetNC( map, Intersection( elms, Image( map ) ) ); end ); From fee40274abdeea57a8dfa899b8e0a6e990ae6cac Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:49:06 +0100 Subject: [PATCH 084/114] Update lib/mapphomo.gi Co-authored-by: Thomas Breuer --- lib/mapphomo.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapphomo.gi b/lib/mapphomo.gi index 01717d8122..13b58c76ec 100644 --- a/lib/mapphomo.gi +++ b/lib/mapphomo.gi @@ -791,7 +791,7 @@ InstallMethod( PreImagesSet, if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); fi; - return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); + return PreImagesSetNC( map, Intersection( elms, Image( map ) ) ); end ); From c76bae66015867f96d47b5c0957aeaa755ba7d9a Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:49:26 +0100 Subject: [PATCH 085/114] Update lib/mapphomo.gi Co-authored-by: Thomas Breuer --- lib/mapphomo.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapphomo.gi b/lib/mapphomo.gi index 13b58c76ec..2a3a2235c0 100644 --- a/lib/mapphomo.gi +++ b/lib/mapphomo.gi @@ -990,7 +990,7 @@ InstallMethod( PreImagesSet, if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); fi; - return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); + return PreImagesSetNC( map, Intersection( elms, Image( map ) ) ); end ); From 275940aeeb8afadccfcce16e83c47b17942f6b48 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:49:50 +0100 Subject: [PATCH 086/114] Update lib/mapphomo.gi Co-authored-by: Thomas Breuer --- lib/mapphomo.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapphomo.gi b/lib/mapphomo.gi index 2a3a2235c0..5d14047e61 100644 --- a/lib/mapphomo.gi +++ b/lib/mapphomo.gi @@ -1098,7 +1098,7 @@ InstallMethod( PreImagesSet, if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); fi; - return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); + return PreImagesSetNC( map, Intersection( elms, Image( map ) ) ); end ); From 994ef080a0a729ca68c29ff5284ac5b56f6b7c09 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:50:33 +0100 Subject: [PATCH 087/114] Update lib/mapping.gi Co-authored-by: Thomas Breuer --- lib/mapping.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapping.gi b/lib/mapping.gi index 651bfda39c..472999ac4a 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -275,7 +275,7 @@ InstallGlobalFunction( PreImage, function ( arg ) fi; if IsDomain( img ) or IsSSortedList( img ) then - return PreImagesSetNC( map, Intersection( img, rng ) ); + return PreImagesSetNC( map, Intersection( img, Image( map ) ) ); elif IsHomogeneousList( img ) then return PreImagesSetNC( map, Intersection( Set( img ), rng ) ); fi; From 0adad7d12954beb1d6e443f19ede90f6f002bd95 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:52:12 +0100 Subject: [PATCH 088/114] Update lib/mapping.gd Co-authored-by: Thomas Breuer --- lib/mapping.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapping.gd b/lib/mapping.gd index c3385a81f7..d0c973b57c 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -1077,7 +1077,7 @@ DeclareOperation( "PreImagesRepresentativeNC", [ IsGeneralMapping, IsObject ] ); ## and the new PreImagesSet checks that elms is a ## subset of the range before calling PreImagesSetNC. ## If elm is a subset the range but not a subset of the image then -## PreImagesSetNC( map, Intersection( elms, Range(map) ) is returned. +## PreImagesSetNC( map, Intersection( elms, Image(map) ) is returned. ## If elms is not a subset of the range then an error is signalled. ##

## When using PreImagesSetNC anything may happen if elms From 648454f8d6e9433b67e67c4c156b5ca332eba0d3 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:52:33 +0100 Subject: [PATCH 089/114] Update lib/mapphomo.gi Co-authored-by: Thomas Breuer --- lib/mapphomo.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapphomo.gi b/lib/mapphomo.gi index 5d14047e61..471926d265 100644 --- a/lib/mapphomo.gi +++ b/lib/mapphomo.gi @@ -1139,7 +1139,7 @@ InstallMethod( PreImagesSet, if not IsSubset( Range( map ), elms ) then Error( " is not a subset of the range of " ); fi; - return PreImagesSetNC( map, Intersection( elms, Range( map ) ) ); + return PreImagesSetNC( map, Intersection( elms, Image( map ) ) ); end ); From ff611b0f44ec5d11ab4d6810fa8d0dc47b7f69fd Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:52:56 +0100 Subject: [PATCH 090/114] Update lib/mapping.gi Co-authored-by: Thomas Breuer --- lib/mapping.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapping.gi b/lib/mapping.gi index 472999ac4a..7689dbc92a 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -277,7 +277,7 @@ InstallGlobalFunction( PreImage, function ( arg ) if IsDomain( img ) or IsSSortedList( img ) then return PreImagesSetNC( map, Intersection( img, Image( map ) ) ); elif IsHomogeneousList( img ) then - return PreImagesSetNC( map, Intersection( Set( img ), rng ) ); + return PreImagesSetNC( map, Intersection( Set( img ), Image( map ) ) ); fi; # preimage of the empty list From 5ccc37d8bd641edcd1f1c8bfbabb72ae8ab89756 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:53:22 +0100 Subject: [PATCH 091/114] Update lib/mapping.gi Co-authored-by: Thomas Breuer --- lib/mapping.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapping.gi b/lib/mapping.gi index 7689dbc92a..49d4a1c059 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -381,7 +381,7 @@ InstallGlobalFunction( PreImages, function ( arg ) fi; if IsDomain( img ) or IsSSortedList( img ) then - return PreImagesSetNC( map, Intersection( img, rng ) ); + return PreImagesSetNC( map, Intersection( img, Image( map ) ) ); elif IsHomogeneousList( img ) then return PreImagesSet( map, Intersection( Set( img ), rng ) ); fi; From a122e743e3979be08800c22aca3220e450231564 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Fri, 17 Jul 2026 17:54:45 +0100 Subject: [PATCH 092/114] Update lib/mapping.gi Co-authored-by: Thomas Breuer --- lib/mapping.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapping.gi b/lib/mapping.gi index 49d4a1c059..86945f23e2 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -383,7 +383,7 @@ InstallGlobalFunction( PreImages, function ( arg ) if IsDomain( img ) or IsSSortedList( img ) then return PreImagesSetNC( map, Intersection( img, Image( map ) ) ); elif IsHomogeneousList( img ) then - return PreImagesSet( map, Intersection( Set( img ), rng ) ); + return PreImagesSetNC( map, Intersection( Set( img ), Image( map ) ) ); fi; # preimage of the empty list From 994c6b2eadb4f646af345de964dd7c07caef9728 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 17 Jul 2026 18:02:00 +0100 Subject: [PATCH 093/114] query in mapprep.gi answered by Thomas --- lib/mapprep.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapprep.gi b/lib/mapprep.gi index a72a05bd34..1cbd95cd3f 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -313,7 +313,7 @@ InstallMethod( PreImagesElmNC, local im; im:= PreImagesElmNC( com!.map2, elm ); if not IsEmpty( im ) then - return PreImagesSetNC( com!.map1, im ); ## why Set and not Elm here ?? + return PreImagesSetNC( com!.map1, im ); else return []; fi; From 93b86b0ce8c5d2fb67fe84415c1141d14c18a59c Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Mon, 20 Jul 2026 17:36:47 +0100 Subject: [PATCH 094/114] Update lib/mapprep.gi Co-authored-by: Thomas Breuer --- lib/mapprep.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapprep.gi b/lib/mapprep.gi index 1cbd95cd3f..af3ca90383 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -1415,7 +1415,7 @@ InstallMethod( PreImageElm, ############################################################################# ## -#M PreImagesElmMC( , ) . . . for identity mapping and element +#M PreImagesElmNC( , ) . . . for identity mapping and element #M PreImagesElm( , ) . . . . for identity mapping and element ## InstallMethod( PreImagesElmNC, From fbb579f5fd08e7f4fa38a8f2f664b630e99ff934 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Mon, 20 Jul 2026 18:28:02 +0100 Subject: [PATCH 095/114] adjusted the documentation in 32.5 --- lib/mapping.gd | 57 +++++++------------------------------------------- 1 file changed, 8 insertions(+), 49 deletions(-) diff --git a/lib/mapping.gd b/lib/mapping.gd index d0c973b57c..a358a28708 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -1038,7 +1038,7 @@ DeclareOperation( "PreImageElm", ## map then returns a ## representative of the set of preimages of elm under map. ##

-## From &GAP; version 4.16.1 PreImagesRepresentative +## From &GAP; version 4.16.1 ther operation PreImagesRepresentative ## was renamed PreImagesRepresentativeNC throughout the library, ## and the new PreImagesRepresentative checks that elm is an ## element of the image before calling PreImagesRepresentativeNC. @@ -1076,8 +1076,9 @@ DeclareOperation( "PreImagesRepresentativeNC", [ IsGeneralMapping, IsObject ] ); ## has been renamed PreImagesSetNC throughout the library, ## and the new PreImagesSet checks that elms is a ## subset of the range before calling PreImagesSetNC. -## If elm is a subset the range but not a subset of the image then -## PreImagesSetNC( map, Intersection( elms, Image(map) ) is returned. +## If elms is a subset of the range but not a subset of the image then +## the returned set is +## PreImagesSetNC( map, Intersection( elms, Image(map) ). ## If elms is not a subset of the range then an error is signalled. ##

## When using PreImagesSetNC anything may happen if elms @@ -1108,32 +1109,8 @@ DeclareOperation( "PreImagesSetNC", [ IsGeneralMapping, IsListOrCollection ] ); ## Label="set of preimages of a collection under a general mapping"/> ## ## -## PreImage( map ) is the preimage of the general mapping -## map, i.e., the subset of elements of the source of map -## that actually have values under map. -## Note that in this case the argument may also be non-injective or -## non-surjective. -##

-## PreImage( map, elm ) is the preimage of the element -## elm of the range of the injective and surjective mapping -## map under map, i.e., the unique element of the source -## which is mapped under map to elm. -## Note that map must be injective and surjective -## (see ). -##

-## PreImage( map, coll ) is the preimage of the subset -## coll of the range of the general mapping map under -## map, i.e., the subset of the source which is mapped under -## map to elements of coll. coll may be a proper set -## or a domain. -## The result will be either a proper set or a domain. -## Note that in this case map may also be non-injective or -## non-surjective. -## (If coll and the result are lists then the positions of -## entries do in general not correspond.) -##

-## -## delegates to when +## PreImage is a global function with three delegations. +## It delegates to when ## called with one argument, ## and to resp. when ## called with two arguments. @@ -1173,26 +1150,8 @@ DeclareGlobalFunction( "PreImage" ); ## Label="set of preimages of a collection under a general mapping"/> ## ## -## PreImages( map ) is the preimage of the general mapping -## map, i.e., the subset of elements of the source of map -## that have actually values under map. -##

-## PreImages( map, elm ) is the set of preimages of the -## element elm of the range of the general mapping map under -## map, i.e., the set of elements of the source which map maps -## to elm. -##

-## PreImages( map, coll ) is the set of images of the -## subset coll of the range of the general mapping map under -## map, i.e., the subset of the source which map maps to -## elements of coll. -## coll may be a proper set or a domain. -## The result will be either a proper set or a domain. -## (If coll and the result are lists then the positions of -## entries do in general not correspond.) -##

-## -## delegates to when called with one argument, +## PreImages is a global function with three delegations. +## It delegates to when called with one argument, ## and to resp. when ## called with two arguments. ##

From 2d68eea6a95a05ac00535131545168a3c71ebbd4 Mon Sep 17 00:00:00 2001 From: Thomas Breuer Date: Thu, 16 Jul 2026 09:21:33 +0200 Subject: [PATCH 096/114] Fix `BaumClausenInfo` when the pcgs is not G-invariant (#6459) --- lib/ctblsolv.gi | 8 ++++---- tst/testbugfix/2026-07-13-Irr.tst | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 tst/testbugfix/2026-07-13-Irr.tst diff --git a/lib/ctblsolv.gi b/lib/ctblsolv.gi index fc787a2bb6..6f055a4bbd 100644 --- a/lib/ctblsolv.gi +++ b/lib/ctblsolv.gi @@ -992,6 +992,7 @@ InstallMethod( BaumClausenInfo, invX, # inverse of `X' D_gi, # hom, # homomorphism to adjust the composition series + ds, # series in the image of `hom' orb, # Forb, # sigma, pi, # permutations needed in the fusion case @@ -1064,15 +1065,14 @@ InstallMethod( BaumClausenInfo, # a list of subgroups such that any composition series through # `ds' from `G' down to the residuum is a chief series. pcgs:= []; + ds:= List( ssr.ds, U -> ImagesSet( hom, U ) ); for i in [ 2 .. Length( ssr.ds ) ] do - j:= NaturalHomomorphismByNormalSubgroupNC( ssr.ds[ i-1 ], ssr.ds[i] ); + j:= NaturalHomomorphismByNormalSubgroupNC( ds[ i-1 ], ds[i] ); Append( pcgs, List( SpecialPcgs( ImagesSource( j ) ), x -> PreImagesRepresentativeNC( j, x ) ) ); od; - Append( pcgs, SpecialPcgs( Last(ssr.ds) ) ); + Append( pcgs, SpecialPcgs( Last( ds ) ) ); G:= ImagesSource( hom ); - pcgs:= List( pcgs, x -> ImagesRepresentative( hom, x ) ); - pcgs:= Filtered( pcgs, x -> Order( x ) <> 1 ); pcgs:= PcgsByPcSequence( ElementsFamily( FamilyObj( G ) ), pcgs ); cs:= PcSeries( pcgs ); lg:= Length( pcgs ); diff --git a/tst/testbugfix/2026-07-13-Irr.tst b/tst/testbugfix/2026-07-13-Irr.tst new file mode 100644 index 0000000000..7c741cde36 --- /dev/null +++ b/tst/testbugfix/2026-07-13-Irr.tst @@ -0,0 +1,8 @@ +# See https://github.com/gap-system/gap/issues/6457 +gap> START_TEST( "2026-07-13-Irr.tst"); + +# `SmallGroup( 384, 5761 )` +gap> IrrBaumClausen( PcGroupCode( 3070794187849707469814486105098811742240, 384 ) );; + +# +gap> STOP_TEST( "2026-07-13-Irr.tst"); From e817c22b4dd5291ad2dc129afcc2c0f0cad39fc4 Mon Sep 17 00:00:00 2001 From: Alexander Hulpke Date: Fri, 17 Jul 2026 16:42:49 -0600 Subject: [PATCH 097/114] Automorphism cleanup (#6462) * Commented variables in autsr * PERFORMANCE: Make sure group knows it is autom. * Set flag that triggers the standard handling of automorphism groups. --- lib/autsr.gi | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/autsr.gi b/lib/autsr.gi index bd4367421a..9cfbbc61b2 100644 --- a/lib/autsr.gi +++ b/lib/autsr.gi @@ -155,6 +155,7 @@ local epi:=EpimorphismFromFreeGroup(sub); free:=Source(epi); + sub:=TrivialSubgroup(M); cnt:=0; while Size(sub)fail then - # t:=ImagesRepresentative(phom,trick); - # # try the trickrels result first - # enum:=Concatenation([t],AsList(enum)); - #fi; - for ep in enum do e:=PreImagesRepresentativeNC(phom,ep); psim:=e*miso; @@ -1121,6 +1116,7 @@ local a:=List(b,x->ConjugatorAutomorphism(Source(AQ.1),x)); b:=Filtered(GeneratorsOfGroup(AQ),x->not HasConjugatorOfConjugatorIsomorphism(x)); a:=Concatenation(a,b); + SetIsAutomorphismGroup(AQ,true); b:=InnerAutomorphismsAutomorphismGroup(AQ); AQ:=Group(a,One(AQ)); SetInnerAutomorphismsAutomorphismGroup(AQ,b); From 5ddc87f7d9e825bc70c0078d8a36ba32356c1916 Mon Sep 17 00:00:00 2001 From: Alexander Hulpke Date: Sat, 18 Jul 2026 17:27:03 -0600 Subject: [PATCH 098/114] Add SpeedupDataPcHom (#6449) Implements a chunked caching scheme for evaluating bijective GroupGeneralMappingByPcgs homomorphisms on PC words. Splits the source pcgs into chunks, caching linear combinations of generator images per exponent pattern, with the bottom elementary abelian layer handled via a matrix over the corresponding prime field. Includes a corresponding ImagesRepresentative method that uses this cached data for a >2.5x speedup, per the included GAPDoc example. --- lib/ghompcgs.gd | 109 +++++++++++++++ lib/ghompcgs.gi | 179 ++++++++++++++++++++++++ tst/teststandard/opers/PcHomSpeedup.tst | 58 ++++++++ 3 files changed, 346 insertions(+) create mode 100644 tst/teststandard/opers/PcHomSpeedup.tst diff --git a/lib/ghompcgs.gd b/lib/ghompcgs.gd index 63f44f7596..bf9abf22e3 100644 --- a/lib/ghompcgs.gd +++ b/lib/ghompcgs.gd @@ -119,3 +119,112 @@ DeclareRepresentation( "IsPcgsToPcgsGeneralMappingByImages", "rangePcgs", "rangePcgsPreimages" ] ); DeclareSynonym( "IsPcgsToPcgsHomomorphism", IsPcgsToPcgsGeneralMappingByImages and IsMapping); + +############################################################################# +## +#A SpeedupDataPcHom( ) +## +## <#GAPDoc Label="SpeedupDataPcHom"> +## +## +## +## +## This attribute can be used to speed up the evaluation of automorphisms +## defined on pc groups +## For a bijective GroupGeneralMappingByPcgs hom whose source +## and range coincide, this attribute computes auxiliary data that +## is used to evaluate hom (via ) +## more efficiently on elements given as PC words. +##

+## The underlying idea is to chop the source pcgs into consecutive chunks +## of generators, and -- for each chunk -- cache the linear combination of +## the images of the chunk's pcgs generators corresponding to a given +## exponent vector, indexed via an enumeration of all exponent vectors for +## that chunk. If the bottom layer of the pcgs corresponds to an +## elementary abelian characteristic section of the group, that layer is +## instead handled by a single matrix (over the corresponding prime +## field) describing the induced linear action, which avoids caching an +## exponential number of images. +##

+## The data returned is a record with components groupData (itself +## a record, cached on the source group, describing the pcgs, the chunk +## boundaries depths, the enumeration functions pats for +## each chunk, and the bottom-layer field, if any), mat (the +## bottom-layer action matrix, or fail if there is none), and +## vals (the (initially empty) per-chunk caches of already computed +## linear combinations). +##

+## c:= +## > 795907704596091686712646038905184706593454298469413373797143285153657747\ +## > 351239586262811710749847738976801000754254026040413579046667526466817130\ +## > 802914392952057538792583640445109649600520674698702973723709697810007373\ +## > 995233352187116591143677686258788327453115978744358269535782002029058318\ +## > 257810771066005080889842841087624746370436252682688197604003291620050028\ +## > 846401909466242477914863426492367981611326065610744459532482363544128183\ +## > 604374827708984459564333504764988635016199760594017468033192923946773034\ +## > 271770646937977241649366365016081229348787914203827648812957496851490453\ +## > 241282156106350395799951977534893207577655765871551105496570960614315334\ +## > 053994514353225444855671606481854013179019965035204709283566628789385554\ +## > 419928011419194010887928919720468833278109533276505173824168955123284931\ +## > 001265659454767607182439296171623310796817449741182968155870079586170364\ +## > 119024273084749477859421889660225177004903125725448515527934855500266332\ +## > 704103204371694822574479313082827045452619695412612791277277701430890177\ +## > 221327579098337215352541159848448340430707754477742647984659147310320792\ +## > 862576023639631550894467198294544031652869769649601433223221326429951;; +## gap> +## gap> g:=PcGroupCode(c,67108864); +## +## gap> pcgs:=Pcgs(g); +## Pcgs([ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, +## f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26 ]) +## gap> +## gap> mat:= +## > [[0,1,1,0,0,1,1,0,1,1,1,1,1,1,1,0,1,1,1,0,1,0,0,1,1,1], +## > [0,0,1,1,0,1,1,1,0,1,0,0,1,0,0,0,0,0,1,1,1,0,0,1,1,1], +## > [0,1,0,0,0,0,0,1,0,1,0,1,0,1,1,1,0,0,1,1,0,1,1,1,0,0], +## > [1,0,0,0,0,0,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,0,0,1,0,0], +## > [1,1,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,0,0,1,0,1,0], +## > [1,1,1,0,0,0,1,0,1,1,1,1,1,1,1,0,0,0,1,0,0,0,1,0,0,1], +## > [1,0,1,0,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,1,1,1,1], +## > [1,0,1,0,1,0,0,1,1,1,0,1,0,0,0,1,1,1,1,0,1,1,1,1,1,0], +## > [0,0,1,0,1,1,1,1,1,1,1,1,1,0,0,0,1,1,0,0,1,0,0,1,0,1], +## > [1,1,0,0,1,0,0,1,1,1,0,0,0,1,1,0,1,0,1,1,1,0,1,1,1,1], +## > [0,0,1,0,1,1,1,1,0,1,0,1,1,0,0,0,1,1,0,0,1,1,1,1,1,0], +## > [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0], +## > [1,0,1,0,1,0,0,0,1,1,0,1,1,0,0,1,1,1,0,1,1,1,0,0,1,1], +## > [0,1,1,1,0,1,1,1,0,1,0,0,1,1,0,0,1,1,0,0,0,0,0,1,1,1], +## > [1,0,1,0,1,0,0,0,1,1,0,1,0,0,1,1,1,0,0,1,1,0,1,1,0,1], +## > [1,0,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,0,1,1,1,1,0,1,1,0], +## > [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,1,0], +## > [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,1,0], +## > [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0], +## > [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,0], +## > [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,1,0], +## > [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0], +## > [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0], +## > [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0], +## > [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,0,0,0,0], +## > [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,0,0,1,1]];; +## gap> a:=GroupHomomorphismByImages(g,g,pcgs,List(mat,x-> +## > PcElementByExponents(pcgs,x)));; +## gap> IsBijective(a); +## true +## gap> r:=List([1..50000],x->Random(g));; +## gap> List(r,x->ImagesRepresentative(a,x));; +## gap> t1:=Runtime();; +## gap> List(r,x->ImagesRepresentative(a,x));; +## gap> t1:=Runtime()-t1;; +## gap> SpeedupDataPcHom(a);; # force caching +## gap> t2:=Runtime();; +## gap> List(r,x->ImagesRepresentative(a,x));; +## gap> t2:=Runtime()-t2;; +## gap> t1/t2>5/2; # speedup better than factor 2.5 +## true +## ]]> +## +## +## <#/GAPDoc> +## +DeclareAttribute("SpeedupDataPcHom",IsGroupGeneralMappingByPcgs,"mutable"); + diff --git a/lib/ghompcgs.gi b/lib/ghompcgs.gi index 7640a62a57..716721c710 100644 --- a/lib/ghompcgs.gi +++ b/lib/ghompcgs.gi @@ -725,3 +725,182 @@ end ); InstallMethod( IsomorphismPcGroup, [ IsPcGroup ], SUM_FLAGS, IdentityMapping ); + + +############################################################################# +## +#A SpeedupDataPcHom( ) +## +BindGlobal("SPHPatternEnumerateFunction",function(pat) +local c; # vector of suffix products linearizing a multiadic index + c:=List([1..Length(pat)],x->Product(pat{[x+1..Length(pat)]})); + return a->a*c; +end); + +InstallMethod(SpeedupDataPcHom,"pcgs",true, + [IsGroupGeneralMappingByPcgs and IsTotal],0, +function(hom) +local g, # Source(hom) + r, # the speedup-data record (cached or freshly computed) + pcgs, # the source pcgs hom!.sourcePcgs + ro, # relative orders of pcgs + n, # length of pcgs + s, # characteristic series, then its bottom elem.-abelian layer + field, # field of that bottom layer (or fail if none) + depths, # the chosen chunk-boundary depths within pcgs + pats, # the per-chunk PatternEnumerateFunction list + mat, # the bottom-level action matrix (or fail) + a, # chunk-size target / exponent-vector temporary + i; # working depth / loop index + + g:=Source(hom); + if g<>Range(hom) or not IsBijective(hom) then + TryNextMethod(); + fi; + r:=fail; + if IsBound(g!.automSpeedupData) then + r:=g!.automSpeedupData; + if r.pcgs<>hom!.sourcePcgs then + r:=fail; + g:=Group(hom!.sourcePcgs); + fi; + fi; + if r=fail then + pcgs:=hom!.sourcePcgs; + ro:=RelativeOrders(pcgs); + n:=Length(pcgs); + # Find the largest characteristic elementary abelian subgroup + # that is a tail of this pcgs. The automorphism acts on this tail + # as a matrix over the corresponding prime field. + s:=AGSRCharacteristicSeries(g,g); + s:=Filtered(s,x->Size(x)=1 or x=SubgroupNC(g,pcgs{[Minimum( + List(GeneratorsOfGroup(x),y->DepthOfPcElement(pcgs,y)))..n]})); + s:=Filtered(s,x->IsElementaryAbelian(x) and Size(x)>1); + if Length(s)>0 then + s:=s[1]; + i:=Minimum(List(GeneratorsOfGroup(s),x->DepthOfPcElement(pcgs,x))); + field:=GF(ro[i]); + depths:=[i,n+1]; + else + field:=fail; + depths:=[n+1]; + i:=n+1; + fi; + + if i>1 then + # how to split further? + a:=Product(ro{[1..n]}); + if a<1000 then + a:=1000; + else + # we want to store about 1000 images, so rounded down log base 1000/10 + a:=RootInt(a,LogInt(a,100))*ro[1]; + fi; + + # now chunks + while i>1 do + i:=i-1; + s:=i; + while s>1 and Product(ro{[s..i]})fail then + # Compute the matrix describing the action of hom on the bottom + # elementary abelian layer. + n:=Length(r.pcgs); + i:=r.depths[Length(r.depths)-1]; + mat:=List(hom!.sourcePcgsImages{[i..n]}, + x->ExponentsOfPcElement(r.pcgs,x){[i..n]}); + mat:=ImmutableMatrix(r.field,mat*One(r.field)); + else + mat:=fail; + fi; + + r:=rec(groupData:=r,mat:=mat,vals:=List(r.pats,x->[])); + return r; +end); + +InstallMethod( ImagesRepresentative, + "for sped-up pc hom",FamSourceEqFamElm, + [ IsGroupGeneralMappingByPcgs and IsTotal + and HasSpeedupDataPcHom, + IsMultiplicativeElementWithInverse and IsNBitsPcWordRep],100, +function(hom,elm) +local r, # SpeedupDataPcHom(hom): the per-hom speedup data + rg, # r.groupData: shared pcgs/depths/field/pattern data + depths, # rg.depths: the chunk boundaries + pcgs, # rg.pcgs + n, # length of pcgs + ld, # length of depths + top, # highest chunk index handled via cached linear combinations + v, # the accumulating image element + e, # exponent vector of elm w.r.t. pcgs + a, # current chunk's exponents, then its matrix image + b, # pattern index into the value cache / a depth bound + i; # loop index + + r:=SpeedupDataPcHom(hom); + if r=fail then TryNextMethod();fi; + rg:=r.groupData; + depths:=rg.depths; + # in next line subtract 1 to use the lowest level matrix + ld:=Length(depths); + pcgs:=rg.pcgs; + n:=Length(pcgs); + + v:=OneOfPcgs(pcgs); + e:=ExponentsOfPcElement(pcgs,elm); + + if rg.field=fail then + top:=ld; + else + top:=ld-1; + fi; + + for i in [1..top-1] do + a:=e{[depths[i]..depths[i+1]-1]}; + b:=rg.pats[i](a)+1; # patterns start at 0 + if not IsBound(r.vals[i][b]) then + r.vals[i][b]:=LinearCombinationPcgs( + hom!.sourcePcgsImages{[depths[i]..depths[i+1]-1]},a); + fi; + v:=v*r.vals[i][b]; + od; + if rg.field=fail then return v;fi; + b:=depths[ld-1]; + a:=e{[b..n]}; + a:=a*One(rg.field); + ConvertToVectorRep(a,Size(rg.field)); + a:=a*r.mat; + + b:=b-1; + e:=0*e; + for i in [1..Length(a)] do + e[b+i]:=Int(a[i]); + od; + return v*PcElementByExponentsNC(pcgs,e); + +end); + + diff --git a/tst/teststandard/opers/PcHomSpeedup.tst b/tst/teststandard/opers/PcHomSpeedup.tst new file mode 100644 index 0000000000..903fc28efa --- /dev/null +++ b/tst/teststandard/opers/PcHomSpeedup.tst @@ -0,0 +1,58 @@ +gap> START_TEST("PcHomSpeedup.tst"); +gap> c:= +> 795907704596091686712646038905184706593454298469413373797143285153657747\ +> 351239586262811710749847738976801000754254026040413579046667526466817130\ +> 802914392952057538792583640445109649600520674698702973723709697810007373\ +> 995233352187116591143677686258788327453115978744358269535782002029058318\ +> 257810771066005080889842841087624746370436252682688197604003291620050028\ +> 846401909466242477914863426492367981611326065610744459532482363544128183\ +> 604374827708984459564333504764988635016199760594017468033192923946773034\ +> 271770646937977241649366365016081229348787914203827648812957496851490453\ +> 241282156106350395799951977534893207577655765871551105496570960614315334\ +> 053994514353225444855671606481854013179019965035204709283566628789385554\ +> 419928011419194010887928919720468833278109533276505173824168955123284931\ +> 001265659454767607182439296171623310796817449741182968155870079586170364\ +> 119024273084749477859421889660225177004903125725448515527934855500266332\ +> 704103204371694822574479313082827045452619695412612791277277701430890177\ +> 221327579098337215352541159848448340430707754477742647984659147310320792\ +> 862576023639631550894467198294544031652869769649601433223221326429951;; +gap> g:=PcGroupCode(c,67108864); + +gap> pcgs:=Pcgs(g);; +gap> mat:= +> [[0,1,1,0,0,1,1,0,1,1,1,1,1,1,1,0,1,1,1,0,1,0,0,1,1,1], +> [0,0,1,1,0,1,1,1,0,1,0,0,1,0,0,0,0,0,1,1,1,0,0,1,1,1], +> [0,1,0,0,0,0,0,1,0,1,0,1,0,1,1,1,0,0,1,1,0,1,1,1,0,0], +> [1,0,0,0,0,0,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,0,0,1,0,0], +> [1,1,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,0,0,1,0,1,0], +> [1,1,1,0,0,0,1,0,1,1,1,1,1,1,1,0,0,0,1,0,0,0,1,0,0,1], +> [1,0,1,0,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,1,1,1,1], +> [1,0,1,0,1,0,0,1,1,1,0,1,0,0,0,1,1,1,1,0,1,1,1,1,1,0], +> [0,0,1,0,1,1,1,1,1,1,1,1,1,0,0,0,1,1,0,0,1,0,0,1,0,1], +> [1,1,0,0,1,0,0,1,1,1,0,0,0,1,1,0,1,0,1,1,1,0,1,1,1,1], +> [0,0,1,0,1,1,1,1,0,1,0,1,1,0,0,0,1,1,0,0,1,1,1,1,1,0], +> [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0], +> [1,0,1,0,1,0,0,0,1,1,0,1,1,0,0,1,1,1,0,1,1,1,0,0,1,1], +> [0,1,1,1,0,1,1,1,0,1,0,0,1,1,0,0,1,1,0,0,0,0,0,1,1,1], +> [1,0,1,0,1,0,0,0,1,1,0,1,0,0,1,1,1,0,0,1,1,0,1,1,0,1], +> [1,0,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,0,1,1,1,1,0,1,1,0], +> [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,1,0], +> [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,1,0], +> [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0], +> [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,0], +> [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,1,0], +> [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0], +> [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0], +> [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0], +> [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,0,0,0,0], +> [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,0,0,1,1]];; +gap> a:=GroupHomomorphismByImages(g,g,pcgs,List(mat,x-> +> PcElementByExponents(pcgs,x)));; +gap> IsBijective(a); +true +gap> r:=List([1..1000],x->Random(g));; +gap> expected:=List(r,x->ImagesRepresentative(a,x));; +gap> SpeedupDataPcHom(a);; +gap> expected=List(r,x->ImagesRepresentative(a,x)); +true +gap> STOP_TEST("PcHomSpeedup.tst"); From 1885aa5d74ae90700c4bf94e12ded9c4af35dc81 Mon Sep 17 00:00:00 2001 From: Alexander Hulpke Date: Sun, 19 Jul 2026 16:31:18 -0600 Subject: [PATCH 099/114] Fix a bug that could lead to `ContainedConjugates` returning too many results (i.e., with some entries representing the same conjugacy classes) (#6460) When mapping perm orbits first in DoConjugateInto, avoid duplication if orbit images are equivalent. Co-authored-by: Alexander Hulpke Co-authored-by: Max Horn Co-authored-by: Codex --- lib/csetgrp.gi | 51 ++++++++++++++++--- .../2026-02-28-ContainedConjugates.tst | 25 +++++++++ tst/testinstall/grpperm.tst | 2 +- 3 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 tst/testbugfix/2026-02-28-ContainedConjugates.tst diff --git a/lib/csetgrp.gi b/lib/csetgrp.gi index c2d37bfba8..ad926d772f 100644 --- a/lib/csetgrp.gi +++ b/lib/csetgrp.gi @@ -84,7 +84,9 @@ end ); # Find element in G to conjugate B into A # call with G,A,B; InstallGlobalFunction(DoConjugateInto,function(g,a,b,onlyone) -local cla,clb,i,j,k,bd,r,rep,b2,dc, +# For the orbit matching below, dc stores candidate data, while clu groups +# completed results whose final B-orbit partitions are A-conjugate. +local cla,clb,i,j,k,bd,r,rep,b2,dc,clu, gens,conjugate; Info(InfoCoset,2,"call DoConjugateInto ",Size(g)," ",Size(a)," ",Size(b)); @@ -171,16 +173,53 @@ local cla,clb,i,j,k,bd,r,rep,b2,dc, od; if Length(dc)>0 then g:=Stabilizer(g,cla,OnTuplesSets);fi; rep:=[]; - for i in dc do - r:=DoConjugateInto(g,a,b^i[2],onlyone); + for i in [1..Length(dc)] do + r:=DoConjugateInto(g,a,b^dc[i][2],onlyone); if onlyone then - if r<>fail then return i[2]*r;fi; + if r<>fail then return dc[i][2]*r;fi; else - if r<>fail then Append(rep,List(r,x->i[2]*x));fi; + if r<>fail then + Append(rep,List(r,x->dc[i][2]*x)); + fi; fi; od; if onlyone then return fail; #otherwise would have found and stopped - else return rep;fi; + else + # Recursive conjugation can change a candidate's orbit partition, + # so cluster the completed results by their final partitions. + clu:=[]; + for i in [1..Length(rep)] do + b2:=OnSetsSets(Set(clb),rep[i]); + j:=First([1..Length(clu)],x->RepresentativeAction(a, + OnSetsSets(Set(clb),rep[clu[x][1]]),b2,OnSetsSets)<>fail); + if j=fail then + Add(clu,[i]); + else + Add(clu[j],i); + fi; + od; + + r:=rep; + rep:=[]; + for i in clu do + if Length(i)=1 then + Add(rep,r[i[1]]); + else + Info(InfoCoset,2,"Testing ",i," for conjugacy"); + bd:=[]; + for j in i do + k:=b^r[j]; + if not ForAny(bd,x->RepresentativeAction(a,x,k)<>fail) then + Add(rep,r[j]); + Add(bd,k); + else + Info(InfoCoset,2,"Eliminated conjugate"); + fi; + od; + fi; + od; + return rep; + fi; fi; else # orbits are fixed. Make sure b is so diff --git a/tst/testbugfix/2026-02-28-ContainedConjugates.tst b/tst/testbugfix/2026-02-28-ContainedConjugates.tst new file mode 100644 index 0000000000..7619f26169 --- /dev/null +++ b/tst/testbugfix/2026-02-28-ContainedConjugates.tst @@ -0,0 +1,25 @@ +# Bug reported by Martin Rubey in forum, Feb 17, 2026 +gap> S := SymmetricGroup(10);; +gap> H := Group([ (3,4), (3,4,5,6,7,8,9,10), (1,2) ]);; +gap> F := Group([ (1,7)(2,8)(5,6), (1,8)(2,7)(3,9)(5,6) ]);; +gap> cc := ContainedConjugates(S, H, F);; +gap> Length(cc); +2 +gap> ForAll(Combinations(cc, 2), +> x -> RepresentativeAction(H, x[1][1], x[2][1]) = fail); +true + +# Regression test for confusing candidate indices with cluster numbers. +gap> S := SymmetricGroup(12);; +gap> H := ClosureGroup( +> Group([ (1,3), (2,6)(5,7), (2,5)(6,7) ]), +> SymmetricGroup([8..12]));; +gap> F := ClosureGroup( +> Group([ (1,6)(2,7) ]), +> SymmetricGroup([8..12]));; +gap> cc := ContainedConjugates(S, H, F);; +gap> Length(cc); +3 +gap> ForAll(Combinations(cc, 2), +> x -> RepresentativeAction(H, x[1][1], x[2][1]) = fail); +true diff --git a/tst/testinstall/grpperm.tst b/tst/testinstall/grpperm.tst index 7ad74c56f2..19fba84d57 100644 --- a/tst/testinstall/grpperm.tst +++ b/tst/testinstall/grpperm.tst @@ -109,7 +109,7 @@ gap> b:=Stabilizer(sym,[[5,6,7],[8,9,10],[11,12],[13]],OnTuplesSets);; gap> Index(sym,b); 3603600 gap> Length(ContainedConjugates(sym,a,b)); -5 +3 gap> TwoClosure(SymmetricGroup([3..6])); Sym( [ 3 .. 6 ] ) gap> TwoClosure(AlternatingGroup(6)); From a4c85fcd2108e0e53535016c1cc07021fec0064b Mon Sep 17 00:00:00 2001 From: Alexander Hulpke Date: Thu, 23 Jul 2026 04:40:10 -0500 Subject: [PATCH 100/114] FIX: solvable steps in FittingFree classes (#6466) --- lib/clashom.gi | 4 ++-- tst/testbugfix/2026-07-22-issue-6465.tst | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tst/testbugfix/2026-07-22-issue-6465.tst diff --git a/lib/clashom.gi b/lib/clashom.gi index 16c7c4f9c3..b987536c1b 100644 --- a/lib/clashom.gi +++ b/lib/clashom.gi @@ -1152,8 +1152,8 @@ local cs, # chief series of G N:=cs[i]; Info(InfoHomClass,1,i,":",Index(M,N),"; ",Size(N)); - if HasAbelianFactorGroup(M,N) then - Info(InfoHomClass,2,"abelian factor ignored"); + if HasSolvableFactorGroup(M,N) or IsSubset(N,Socle(G)) then + Info(InfoHomClass,2,"solvable/top factor ignored"); else # nonabelian factor. Now it means real work. diff --git a/tst/testbugfix/2026-07-22-issue-6465.tst b/tst/testbugfix/2026-07-22-issue-6465.tst new file mode 100644 index 0000000000..ecea0a23a2 --- /dev/null +++ b/tst/testbugfix/2026-07-22-issue-6465.tst @@ -0,0 +1,12 @@ +# Regression test for issue #6465: +# https://github.com/gap-system/gap/issues/6465 +# +# ConjugacyClassesFittingFreeGroup could call `NrMovedPoints' on the image +# of `NaturalHomomorphismByNormalSubgroupNC', but that image need not be a +# permutation group (e.g. it can be a pc group), which raised +# "no 1st choice method found for `NrMovedPoints'". +gap> gens:= [ (1,2,5,4,3)(6,7)(9,10)(12,13), +> (1,5)(2,3)(6,11,7,12,8,13,9,14)(10,15) ];; +gap> G:= Group( gens );; +gap> Length( ConjugacyClasses( G ) ); +175 From a24cbd5c6c8e64eb2b6a889c71aa8f6fc1895e24 Mon Sep 17 00:00:00 2001 From: Alexander Hulpke Date: Thu, 23 Jul 2026 06:17:26 -0500 Subject: [PATCH 101/114] FIX: Typos and grammatical errors in comments across Hulpke-authored files (#6467) Corrects misprints and grammatical errors (misspellings, subject/verb agreement, stray commas, non-idiomatic phrasing, etc.) in comments across all files listing Alexander Hulpke as a (co)author. Boilerplate headers, citation keys, GAP identifiers, GAPDoc markup, non-English notes, and genuinely ambiguous/garbled comments were left untouched. Co-authored-by: hulpke Co-authored-by: Claude Sonnet 5 --- grp/glzmodmz.gd | 2 +- grp/simple.gd | 2 +- grp/simple.gi | 2 +- hpcgap/lib/ratfun.gi | 22 +++++++++++----------- lib/addgphom.gd | 2 +- lib/algfld.gd | 4 ++-- lib/algfp.gd | 2 +- lib/algfp.gi | 2 +- lib/autsr.gi | 28 ++++++++++++++-------------- lib/clashom.gd | 6 +++--- lib/clashom.gi | 14 +++++++------- lib/csetgrp.gi | 2 +- lib/csetpc.gi | 4 ++-- lib/csetperm.gi | 2 +- lib/ctblgrp.gd | 8 ++++---- lib/ctblgrp.gi | 14 +++++++------- lib/dicthf.gi | 6 +++--- lib/factgrp.gd | 14 +++++++------- lib/factgrp.gi | 12 ++++++------ lib/fitfree.gd | 6 +++--- lib/fitfree.gi | 4 ++-- lib/galois.gd | 2 +- lib/galois.gi | 4 ++-- lib/ghom.gd | 4 ++-- lib/ghom.gi | 2 +- lib/ghomfp.gd | 4 ++-- lib/ghomfp.gi | 4 ++-- lib/ghompcgs.gi | 4 ++-- lib/gpprmsya.gi | 2 +- lib/groebner.gd | 4 ++-- lib/groebner.gi | 10 +++++----- lib/grpcompl.gi | 2 +- lib/grpfp.gi | 12 ++++++------ lib/grplatt.gd | 4 ++-- lib/grplatt.gi | 6 +++--- lib/grppccom.gi | 4 ++-- lib/grppclat.gd | 2 +- lib/grppclat.gi | 12 ++++++------ lib/grpreps.gi | 2 +- lib/matint.gd | 2 +- lib/matint.gi | 4 ++-- lib/matrix.gd | 2 +- lib/maxsub.gi | 2 +- lib/meatauto.gi | 8 ++++---- lib/meataxe.gd | 2 +- lib/meataxe.gi | 12 ++++++------ lib/morpheus.gd | 4 ++-- lib/morpheus.gi | 22 +++++++++++----------- lib/onecohom.gi | 24 ++++++++++++------------ lib/oprtglat.gd | 2 +- lib/oprtglat.gi | 2 +- lib/permdeco.gd | 6 +++--- lib/permdeco.gi | 2 +- lib/polyfinf.gd | 6 +++--- lib/polyfinf.gi | 2 +- lib/polyrat.gi | 2 +- lib/ratfun.gi | 6 +++--- lib/ratfun1.gi | 6 +++--- lib/ratfunul.gi | 2 +- lib/ringhom.gi | 2 +- lib/ringsc.gd | 6 +++--- lib/schur.gd | 2 +- lib/schur.gi | 2 +- lib/straight.gd | 8 ++++---- lib/system.g | 2 +- lib/teaching.g | 12 ++++++------ lib/teachm2.g | 2 +- lib/teachmod.g | 2 +- lib/twocohom.gi | 8 ++++---- lib/wordass.gi | 4 ++-- lib/wordrep.gi | 16 ++++++++-------- 71 files changed, 213 insertions(+), 213 deletions(-) diff --git a/grp/glzmodmz.gd b/grp/glzmodmz.gd index 05a9c71a87..568d37af28 100644 --- a/grp/glzmodmz.gd +++ b/grp/glzmodmz.gd @@ -24,7 +24,7 @@ DeclareGlobalFunction( "SizeOfGLdZmodmZ" ); ## #F ConstructFormPreservingGroup(oper [,sign] d, R ) ## -## constructs the classical group sefined by oper over a prime field +## constructs the classical group defined by oper over a prime field ## over the residue class ring R, which must be modulo an odd prime ## power. DeclareGlobalFunction("ConstructFormPreservingGroup"); diff --git a/grp/simple.gd b/grp/simple.gd index 7a1db67032..c6b1c556a7 100644 --- a/grp/simple.gd +++ b/grp/simple.gd @@ -134,7 +134,7 @@ DeclareAttribute("DataAboutSimpleGroup",IsGroup,"mutable"); ## For an order n this function returns a heuristic bound for a ## small permutation degree of a simple group of that exact order. ## This function -## can be used to decide whether it is worth to try the `SmallerDegree' +## can be used to decide whether it is worth trying the `SmallerDegree' ## reduction. ## <#/GAPDoc> DeclareGlobalFunction("SufficientlySmallDegreeSimpleGroupOrder"); diff --git a/grp/simple.gi b/grp/simple.gi index c9a595c680..babad7ffd6 100644 --- a/grp/simple.gi +++ b/grp/simple.gi @@ -1029,7 +1029,7 @@ local nam,e,efactors,par,expo,prime,result,aut,i,classical,classaut,shortname, classical:=fail; if id.series="Spor" then nam:=id.name; - # deal wirth stupid names in identification + # deal with stupid names in identification if nam in ["M(11)","M(12)","M(22)","M(23)","M(24)","J(1)","J(3)", "J(4)","Co(3)","Co(2)","Fi(22)","Fi(23)"] then diff --git a/hpcgap/lib/ratfun.gi b/hpcgap/lib/ratfun.gi index 93dd9eb716..6cb578f35f 100644 --- a/hpcgap/lib/ratfun.gi +++ b/hpcgap/lib/ratfun.gi @@ -8,7 +8,7 @@ ## ## SPDX-License-Identifier: GPL-2.0-or-later ## -## This file contains methods for rational functions, laurent +## This file contains methods for rational functions, Laurent ## polynomials and polynomials and their families. ## @@ -596,7 +596,7 @@ end); ## #M PrintObj( ) ## -## This method is installed for all rational function. +## This method is installed for all rational functions. ## InstallMethod( String,"rational function", [ IsRationalFunction ], function( obj ) @@ -823,7 +823,7 @@ function( efam ) SetOne( fam, PolynomialByExtRepNC(fam,[[],fam!.oneCoefficient])); # we will store separate `one's for univariate polynomials. This will - # allow to keep univariate calculations in this one indeterminate. + # allow us to keep univariate calculations in this one indeterminate. fam!.univariateOnePolynomials:=MakeWriteOnceAtomic([]); fam!.univariateZeroPolynomials:=MakeWriteOnceAtomic([]); @@ -835,8 +835,8 @@ function( efam ) end ); -# this method is only to get a reasonable error message in case the ring does -# not know to be a UFD. +# this method is only to get a reasonable error message in case the ring is +# not known to be a UFD. InstallOtherMethod( RationalFunctionsFamily,"not UFD ring", true, [ IsObject ], 0, @@ -1081,7 +1081,7 @@ end); ## InstallMethod( \*, "coeff * rat-fun", IsCoeffsElms, [ IsRingElement, IsPolynomialFunction ], - 3, # so we dont call positive integer * additive element + 3, # so we don't call positive integer * additive element function(c, r) return ProdCoefRatfun(c,r); end); @@ -1093,7 +1093,7 @@ end); ## InstallMethod( \*, "rat-fun * coeff", IsElmsCoeffs, [ IsPolynomialFunction, IsRingElement ], - 3, # so we dont call positive integer * additive element + 3, # so we don't call positive integer * additive element function(r, c) return ProdCoefRatfun(c,r); end); @@ -1711,7 +1711,7 @@ local fam,tw,res,m,n,mn,r,e,s,d,dr,px,x,y,onepol,stop; fi; if n>m then - # force f to be of larger degee + # force f to be of larger degree res:=(onepol)^(n*m); tw:=f; f:=g; g:=tw; tw:=m; m:=n; n:=tw; @@ -1724,7 +1724,7 @@ local fam,tw,res,m,n,mn,r,e,s,d,dr,px,x,y,onepol,stop; return ConstantInBaseRingPol(res*g^m,ind); fi; - # and now we may start really, subresultant algorithm: S_j+1=g, S_j+2=f + # and now we may really start the subresultant algorithm: S_j+1=g, S_j+2=f x:=fam!.oneCoefficient; y:=x; @@ -1759,7 +1759,7 @@ local fam,tw,res,m,n,mn,r,e,s,d,dr,px,x,y,onepol,stop; n:=dr; f:=g; -# was: g:=r/(x*y^mn) However the double division seems more gently; +# was: g:=r/(x*y^mn) However the double division seems more gentle; g:=r/x/y^mn; x:=LeadingCoefficient(f,ind); y:=x^mn/y^(mn-1); @@ -1839,7 +1839,7 @@ end); # # 11-15-04, WDJ and AH -# n is the number of terms in m. n1 is the number of variable occurring +# n is the number of terms in m. n1 is the number of variables occurring # in each monomial term of m. returns the degrees of each variable in the # monomial m. BindGlobal("MVFactorDegreeMonomialTerm",function(m) diff --git a/lib/addgphom.gd b/lib/addgphom.gd index 6a251b67dc..1ad1649847 100644 --- a/lib/addgphom.gd +++ b/lib/addgphom.gd @@ -27,7 +27,7 @@ ## and , and the preimage of each element of is given by ## `( )', where is a {\GAP} function. ## -## No test is performed on whether the functions actually give an +## No test is performed on whether the functions actually give a ## homomorphism between both groups because this would require testing the ## full multiplication table. ## diff --git a/lib/algfld.gd b/lib/algfld.gd index ee85146770..9ed461efca 100644 --- a/lib/algfld.gd +++ b/lib/algfld.gd @@ -184,12 +184,12 @@ DeclareGlobalFunction("AlgExtSquareHensel"); ## ## ## -## Let f be a univariate, rational, irreducible, polynomial. A +## Let f be a univariate, rational, irreducible polynomial. A ## pair g,h of polynomials of degree strictly ## smaller than that of f, such that f(x)|g(h(x)) is ## called an ideal decomposition. In the context of field ## extensions, if \alpha is a root of f in a suitable extension -## and Q the field of rational numbers. Such decompositions correspond +## and Q the field of rational numbers, such decompositions correspond ## to (proper) subfields Q < Q(\beta) < Q(\alpha), ## where g is the minimal polynomial of \beta. ## This function determines such decompositions up to equality of the subfields diff --git a/lib/algfp.gd b/lib/algfp.gd index c8693ee0a4..fcdc8ba208 100644 --- a/lib/algfp.gd +++ b/lib/algfp.gd @@ -94,7 +94,7 @@ DeclareOperation( "MappedExpression", #F FactorFreeAlgebraByRelators( , ) . . . factor of free algebra ## ## is an f.p.~algebra $A$ isomorphic to the factor of the free (associative) -## algebra(-with-one) by the two-sided ideasl spanned by the relators +## algebra(-with-one) by the two-sided ideals spanned by the relators ## in the list . ## ## If is an algebra-with-one then the generators in the list diff --git a/lib/algfp.gi b/lib/algfp.gi index 51adff0b6d..34b9185e6f 100644 --- a/lib/algfp.gi +++ b/lib/algfp.gi @@ -136,7 +136,7 @@ BindGlobal( "MappedExpressionForElementOfFreeAssociativeAlgebra", mapped:= MappedWord( expr[1] ); fi; - # Avoid to multiply explicitly with 1 in order to avoid deep trees. + # Avoid multiplying explicitly with 1 in order to avoid deep trees. if expr[2] <> one then mapped:= expr[2] * mapped; fi; diff --git a/lib/autsr.gi b/lib/autsr.gi index 9cfbbc61b2..942dc30593 100644 --- a/lib/autsr.gi +++ b/lib/autsr.gi @@ -101,7 +101,7 @@ end ); # If M<=Frat(C_G(M)), try to find relators for C/M that in G evaluate to # generators of M and for which exponent sums are multiples of p. In this -# case the values of the relators on pre-images in G do not depend on choice +# case the values of the relators on pre-images in G do not depend on the choice # of representatives and can be used to deduce the module automorphism # belonging to a factor group automorphism. BindGlobal("AGSRFindRels",function(nat,newgens) @@ -318,10 +318,10 @@ local # relator powers) i; # loop index over the relator's generators - # If has an entry 'conjugated' the records is no relator for a + # If has an entry 'conjugated' the record is not a relator for a # presentation,but belongs to relation # (g_i n_i) ^ s_j = - # which is used to determinate normal complements. [i,j] is bound to + # which is used to determine normal complements. [i,j] is bound to # . if IsBound(r.conjugated) then Error("not yet implemented"); @@ -363,7 +363,7 @@ BindGlobal("AGSRAutomLift",function(ocr,nat,fhom,miso) s, # NOTE: multi-role -- exponent matrices from the trick # relators, then the linear solution vector, then the list of # module elements from cocycleToList - ws, # words expresing hom image in generators + ws, # words expressing hom image in generators t, # NOTE: two roles -- (1) the trickrels record, and (2) the # coboundary vector being assembled for cocycleToList l, # NOTE: two roles -- (1) exponent lists/matrices from the @@ -389,7 +389,7 @@ BindGlobal("AGSRAutomLift",function(ocr,nat,fhom,miso) #for ep in Enumerator(ocr.moduleauts) do if ocr.trickrels<>fail then # special case for M<=Frat(C_G(M)). Use special relators for factor that - # allow to deduce corresponding module aut. + # allow deducing corresponding module aut. t:=ocr.trickrels; phom:=IdentityMapping(ocr.moduleauts); @@ -620,7 +620,7 @@ local # now run over all Zuppos (Conjugates of class representatives) in factor that do - # not intersect (the image of) avoid. These, that saisfy, will span the correct subgroup. + # not intersect (the image of) avoid. These, that satisfy, will span the correct subgroup. i:=1; while worked<>fail and i<=Length(c) do @@ -722,7 +722,7 @@ local end); -# Same syntax as `SubgroupProperty`, but assumption that the tests are +# Same syntax as `SubgroupProperty`, but assuming that the tests are # expensive. Thus minimize number of tests by doing more group calculations InstallGlobalFunction(SubgroupConditionAbove,function(G,cond,Sorig) local @@ -748,7 +748,7 @@ local # first, try to find a few elements that work (and catch the case that the - # subgroup has small index. Ensure we test at least once for each possible + # subgroup has small index). Ensure we test at least once for each possible # step. nr:=2^LogInt(Size(G),1000)+Length(Factors(Size(G))); u:=[]; @@ -863,7 +863,7 @@ local pools, # the resulting classes (pools) of normal subgroups (return value) sel, # indices of the subgroups sharing the current fingerprint # -- loop counter -- - i; # loop variable over the distinct fingerprints fingerprint + i; # loop variable over the distinct fingerprints fp:=function(x) local l; # the fingerprint list being assembled (size, class data, abelian @@ -895,7 +895,7 @@ local return pools; end); -# form a characterististic series through radical with elab factors +# form a characteristic series through radical with elab factors InstallGlobalFunction(AGSRCharacteristicSeries,function(G,r) local # -- the series being built -- @@ -1629,7 +1629,7 @@ local j:=j+1; od; - # remove redundant generators. Note that Aperm could be to big, thus + # remove redundant generators. Note that Aperm could be too big, thus # make group from Apa ac:=AGSRReducedGens(SubgroupNC(Parent(sub),Apa),Apa,A); if ac<>fail then @@ -2041,7 +2041,7 @@ local SortBy(cg,x->-Size(x)); SortBy(ch,x->-Size(x)); - # find list of properties, tryign to match them up + # find list of properties, trying to match them up pg:=List(cg,props); ph:=List(ch,props); @@ -2263,10 +2263,10 @@ local # GxG. It is thus sufficient, if we find the subgroup Aut(G)\wr 2. - # We now found that G and H have two characteristic subgroups A,,,,,,,,) ## -## This function computes the classes of a subwreath groiup. The interface +## This function computes the classes of a subwreath group. The interface ## is quite technical because the subwreath decomposition is passed already ## with it: is the factor group, the normal subgroup in it (direct -## product of the groups isomorphic ). is one of these and +## product of the groups isomorphic to ). is one of these and ## the action of on the first component, the components are -## given in , and are embeddings and projectios for the +## given in , and are embeddings and projections for the ## direct product. DeclareGlobalFunction("ConjugacyClassesSubwreath"); diff --git a/lib/clashom.gi b/lib/clashom.gi index b987536c1b..5cbe5995db 100644 --- a/lib/clashom.gi +++ b/lib/clashom.gi @@ -208,7 +208,7 @@ local clT, # classes T # we have taken a permutation representation that prolongates to autT! oci:=CycleStructurePerm(clT[i][1]); - # we have tested already the smaller-# classes + # we have already tested the smaller-# classes pfus:=Filtered([i+1..lcl],j->CycleStructurePerm(clT[j][1])=oci and Size(clT[j][2])=sci); pfus:=Difference(pfus,fus[i]); @@ -793,7 +793,7 @@ local clT, # classes T elif not stabtrue then # we have an element that stabilizes the conjugacy class. # correct this to an element that fixes the representative. - # (As we have taken already the centralizer in + # (As we have already taken the centralizer in # centralizers_r, it is sufficient to correct by # centralizers_r-conjugation.) con:=trans[orpo]*gen; @@ -1077,7 +1077,7 @@ local cs, # chief series of G hom, # G->G/cs[i] M, # cs[i-1] N, # cs[i] - subN, # maximan normal in M over N + subN, # maximal normal in M over N csM, # orbit of nt in M under G n, # Length(csM) T, # List of T_i @@ -1102,7 +1102,7 @@ local cs, # chief series of G genimages,# G.generators Fhom img, # gQhom gimg, # gFhom - act, # component permcation to 1 + act, # component permutation to 1 j,k, # loop clF, # classes of F ncl, # new classes @@ -1126,7 +1126,7 @@ local cs, # chief series of G # classes by lifts via nonabelian factors and can disregard all abelian # factors. - # we will give classes always by their representatives in G and + # we will always give classes by their representatives in G and # centralizers by their full preimages in G. cs:= ChiefSeriesThrough( G,[Socle(G)] ); @@ -1896,7 +1896,7 @@ local classes, # classes to be constructed, the result Assert(1,solvsz=stabrsubsz*Length(orb)); - #nosolvable part + #nonsolvable part orblock:=Length(orb); vp:=1; stabfacgens:=[]; @@ -2837,7 +2837,7 @@ local r, #radical r:=ValueOption("candidatenums"); if r<>fail and HasConjugacyClasses(G) then # candidatenums gives the numbers of some classes in G that should be - # tried first (as they likely contain the element). Us this to reduce + # tried first (as they likely contain the element). Use this to reduce # conjugacy test in factor. if not IsBound(G!.radicalfactorclassmap) then G!.radicalfactorclassmap:=[]; diff --git a/lib/csetgrp.gi b/lib/csetgrp.gi index ad926d772f..36dff6b004 100644 --- a/lib/csetgrp.gi +++ b/lib/csetgrp.gi @@ -1336,7 +1336,7 @@ local c, flip, maxidx, cano, tryfct, p, r, t, cnt:=cnt-1; # compute orbit and stabilizers for the next step - # own Orbitalgorithm and stabilizer computation + # own orbit algorithm and stabilizer computation #while blist[posi] do posi:=posi+1;od; posi:=Position(blist,false,posi); diff --git a/lib/csetpc.gi b/lib/csetpc.gi index 5102f0a186..faa517dd0d 100644 --- a/lib/csetpc.gi +++ b/lib/csetpc.gi @@ -18,12 +18,12 @@ ## Main part of the computation of a canonical coset representative in a ## PcGroup. This is done by factoring with the canonical generators of the ## subgroup to set the appropriate exponents to zero. Since the -## representation as an PcWord is "from left to right", we can multiply with +## representation as a PcWord is "from left to right", we can multiply with ## subgroup elements from _right_, without changing exponents of the ## generators with lower depth (that are supposedly in canonical form yet). ## Since we want _right_ cosets, everything is done with the _inverse_ ## elements, which are representatives for the left cosets. The routine -## supposes, that an Cgs has been set up and the relative orders of the +## supposes, that a Cgs has been set up and the relative orders of the ## generators have been computed by the calling routine. ## InstallMethod(CanonicalRightCosetElement,"Pc",IsCollsElms, diff --git a/lib/csetperm.gi b/lib/csetperm.gi index 4899417c5b..f6072b48e1 100644 --- a/lib/csetperm.gi +++ b/lib/csetperm.gi @@ -44,7 +44,7 @@ end ); ## MAX_SIZE_TRANSVERSAL := 100000; # try to keep transversals shorter than this BITLIST_LIMIT_TRANSVERSAL:=10^8; # absolutely must keep transversals - # shorter, as otheriwse too long bit lists might be produced + # shorter, as otherwise too long bit lists might be produced # so far only orbits and perm groups -- TODO: Other deduced actions InstallGlobalFunction(ActionRefinedSeries,function(G,U) diff --git a/lib/ctblgrp.gd b/lib/ctblgrp.gd index e8a33e4670..f4f5d33035 100644 --- a/lib/ctblgrp.gd +++ b/lib/ctblgrp.gd @@ -24,7 +24,7 @@ ##

## Called with a group G, the function ## returns a character -## table object that stores already information such as class lengths, +## table object that already stores information such as class lengths, ## but not the irreducible characters. ## The routines that compute the irreducibles may use the information that ## is already contained in this table object. @@ -160,10 +160,10 @@ DeclareOperation("DxPreparation",[IsGroup,IsRecord]); ## Comparison is based first on the size of the class and then on the ## order of the representatives. ## Thus the class containing the identity element is in the first position, -## as required. Since sorting is primary by the class sizes,smaller +## as required. Since sorting is primarily by the class sizes,smaller ## classes are in earlier positions, making the active columns those to ## smaller classes, thus reducing the work for calculating class matrices. -## Additionally, galois conjugated classes are kept together, thus increasing +## Additionally, Galois conjugated classes are kept together, thus increasing ## the chance,that with one columns of them active to be several active, ## again reducing computation time. ## @@ -266,7 +266,7 @@ DeclareGlobalFunction("DxOnedimCleanout"); ## ## ## returns the number of the class sum matrix that is assumed to yield the -## best (cost/earning ration) split. This matrix then will be the next one +## best (cost/earning ratio) split. This matrix then will be the next one ## computed and used. ##

## The global option maxclasslen diff --git a/lib/ctblgrp.gi b/lib/ctblgrp.gi index 914845923f..27d37164ea 100644 --- a/lib/ctblgrp.gi +++ b/lib/ctblgrp.gi @@ -44,7 +44,7 @@ InstallGlobalFunction( IsDxLargeGroup, G -> Size(G) > DXLARGEGROUPORDER ); ## classes are in earlier positions,making the active columns those to ## smaller classes,reducing the work for calculating class matrices! ## Additionally galois conjugated classes are together,thus increasing the -## chance,that with one columns of them active to be several acitive, +## chance,that with one columns of them active to be several active, ## reducing computation time ! ## InstallGlobalFunction( ClassComparison, function(c,d) @@ -444,7 +444,7 @@ end ); #F DxLinearCharacters() . . . . calculate characters of G of degree 1 ## ## These characters are computed as characters of G/G'. This can be done -## easily by using the fact,that an abelian group is direct product of +## easily by using the fact,that an abelian group is a direct product of ## cyclic groups. Thus we get the characters as "direct products" of the ## characters of cyclic groups,which can be easily computed. They are ## lifted afterwards back to G. @@ -809,8 +809,8 @@ InstallGlobalFunction(SplitStep,function(D,bestMat) # extra dimension of the larger space might somehow get # lost. Therefore we can't be that tricky as the following # argument supposes. - # In characteristic p the split may be - # not as well,as in characteristic 0. In this + # In characteristic p the split may not be as good + # as in characteristic 0. In this # case,we may find a smaller image in another space. # As character morphisms are a group we will also # have the inverse image of the complement, we can @@ -1408,7 +1408,7 @@ local n,i,val,b,requiredCols,splitBases,wert,nu,r,rs,rc,bn,bw,split, # only take classes small enough if D.classiz[n]<=lim and - # dont start with central classes in small groups! + # don't start with central classes in small groups! (D.classiz[n]>ksl or IsBound(D.maycent)) then for i in [1..Length(D.raeume)] do r:=D.raeume[i]; @@ -1471,7 +1471,7 @@ local n,i,val,b,requiredCols,splitBases,wert,nu,r,rs,rc,bn,bw,split, od; wert[n]:=wert[n]*D.centralizers[n] # *G/|K| - /(Length(rc)); # We count -mistakening - also the first + /(Length(rc)); # We count -mistakenly - also the first # column,that is available for free. Its "costs" are meant to # compensate for the splitting process. fi; @@ -2236,7 +2236,7 @@ local C,u,irr; # Sort the characters by degrees. irr:=SortedCharacters(C,irr); - # Throw away not any longer used components of the Dixon record. + # Throw away components of the Dixon record that are no longer used. for u in Difference(RecNames(D), ["ClassElement","centmulCandidates","centmulMults","characterTable", "classMap","facs","fingerprintCandidates", diff --git a/lib/dicthf.gi b/lib/dicthf.gi index 7347144911..29c50a2a78 100644 --- a/lib/dicthf.gi +++ b/lib/dicthf.gi @@ -292,10 +292,10 @@ InstallMethod(SparseIntKey,"kernel pc group elements",true, IsElementFinitePolycyclicGroup and IsDataObjectRep and IsNBitsPcWordRep],0, function(d,e) local l,p; - # we want to use an small shift to avoid cancellation due to similar bit + # we want to use a small shift to avoid cancellation due to similar bit # patterns in many bytes (the exponent values in most cases are very - # small). The pcgs length is a reasonable small value-- otherwise we get - # already overlap for the generators alone. + # small). The pcgs length is a reasonable small value-- otherwise we + # already get overlap for the generators alone. p:=FamilyObj(e)!.DefiningPcgs; l:=NextPrimeInt(Length(p)+1); p:=Product(RelativeOrders(p)); diff --git a/lib/factgrp.gd b/lib/factgrp.gd index 5b0fc432ff..08517905d4 100644 --- a/lib/factgrp.gd +++ b/lib/factgrp.gd @@ -21,7 +21,7 @@ ## construct one. ## The default method for `NaturalHomomorphismByNormalSubgroupOp' then uses ## two other operations: `DoCheapActionImages' computes actions that come -## naturally from a groups representation (for example permutation action +## naturally from a group's representation (for example permutation action ## on orbits and blocks) and can be computed quickly. This is intended ## as a first test to avoid hard work for homomorphisms that are easy to ## get. @@ -43,7 +43,7 @@ ## ## computes natural actions for G and stores the resulting ## NaturalHomomorphismByNormalSubgroup. The type of the natural actions -## varies with the representation of G, for permutation groups it are for +## varies with the representation of G, for permutation groups these are for ## example constituent and block homomorphisms. ## A method for DoCheapActionImages must register all found actions with ## AddNaturalHomomorphismsPool so they become available. @@ -100,12 +100,12 @@ DeclareInfoClass("InfoFactor"); ## ops is a list which gives the best know actions for each normal ## subgroup. Its entries are either Homomorphisms from G or ## generator lists (G.generators images) or lists of integers. In the -## latter case the factor is subdirect product of the factors with +## latter case the factor is a subdirect product of the factors with ## the given numbers. -## cost gives the difficulty for each actions (degree of permgroup). It -## is used to check whether a new actions is better. +## cost gives the difficulty for each action (degree of permgroup). It +## is used to check whether a new action is better. ## lock is a bitlist, which indicates whether certain actions are -## locked. If this happens, a better new actions is not entered. +## locked. If this happens, a better new action is not entered. ## This allows a computation to access the pool several times and to ## be guaranteed to be returned the same object. Usually a routine ## initially locks and finally unlocks. @@ -114,7 +114,7 @@ DeclareInfoClass("InfoFactor"); ## already ## intersects is a list of all intersections that have already been ## formed. -## blocksdone indicates if the actions already has been improved +## blocksdone indicates if the action already has been improved ## using blocks ## in_code can be set by the code to avoid addition of new actions ## (and thus resorting) diff --git a/lib/factgrp.gi b/lib/factgrp.gi index c4f2306c2a..6c78d43be3 100644 --- a/lib/factgrp.gi +++ b/lib/factgrp.gi @@ -731,7 +731,7 @@ totalcnt, interrupt, u, nu, cor, zzz,bigperm,perm,badcores,max,i,hard; simple:=HasIsNonabelianSimpleGroup(G) and IsNonabelianSimpleGroup(G) and Size(N)=2; uc:=TrivialSubgroup(G); - # look if it is worth to look at action on N + # look if it is worth looking at action on N # if not abelian: later replace by abelian Normal subgroup if IsAbelian(N) and (Size(N)>50 or IndexNC(G,N)Size(N) and IsSubset(cor,N) and not cor in badcores then Add(badcores,cor); fi; - # store known information(we do't act, just store the subgroup). + # store known information(we don't act, just store the subgroup). # Thus this is fairly cheap pool.dotriv:=true; zzz:=AddNaturalHomomorphismsPool(G,cor,u,IndexNC(G,u)); @@ -1148,7 +1148,7 @@ local gimg,img,dom,b,improve,bp,bb,i,k,bestdeg,subo,op,bc,bestblock,bdom, Info(InfoFactor,2,"try all seeds"); # if the degree is not too big or if we are desperate then go for # all blocks - # greedy approach: take always locally best one (otherwise there + # greedy approach: always take the locally best one (otherwise there # might be too much work to do) bestdeg:=Length(dom); bp:=[]; #Blocks pool @@ -1503,7 +1503,7 @@ local pool, dom, bestdeg, blocksdone, o, s, badnormals, cnt, v, u, oo, m, fi; fi; - # then we should look at the orbits of the normal subgroup to see, + # then we should look at the orbits of the normal subgroup to see # whether anything stabilizing can be of use o:=Filtered(OrbitsDomain(N,dom),i->Length(Orbit(G,i[1]))>Length(i)); Apply(o,Set); @@ -1659,7 +1659,7 @@ local proj,h,pool; return IdentityMapping(G); fi; - # check, whether we already know a factormap + # check whether we already know a factormap pool:=NaturalHomomorphismsPool(G); h:=PositionSet(pool.ker,N); if h<>fail and IsGeneralMapping(pool.ops[h]) then @@ -1702,7 +1702,7 @@ local proj,h,pool; Length(MovedPoints(Range(h)))," found"); else Error("I don't know how to find a natural homomorphism for in "); - # nothing had been found, Desperately one could try again, but that + # nothing had been found, desperately one could try again, but that # would create a possible infinite loop. h:= NaturalHomomorphismByNormalSubgroup( G, N ); fi; diff --git a/lib/fitfree.gd b/lib/fitfree.gd index c284d7259c..573f716af9 100644 --- a/lib/fitfree.gd +++ b/lib/fitfree.gd @@ -59,7 +59,7 @@ InstallTrueMethod(CanComputeFittingFree, IsPcGroup); ## ## ## -## Function that encodes (hard-coded) heuristics on whether it is worth to use +## Function that encodes (hard-coded) heuristics on whether it is worth using ## Trivial-Fitting/Solvable Radical methods for problems in permutation ## groups in favor over backtrack solutions. Returns fail if decision ## cannot be made. @@ -88,7 +88,7 @@ DeclareGlobalFunction("AttemptPermRadicalMethod"); ## A list of indices in the pcgs, indicating the G-normal subgroups in ## the series for the pcgs, including an entry for the trivial subgroup. ## pcisom An effective isomorphism from a supergroup of Rad(G) to a pc group -## factorhom A epimorphism from G onto G/Rad(G), +## factorhom An epimorphism from G onto G/Rad(G), ## the image group being ## represented in a way that decomposition into generators will work ## efficiently. In particular, it is possible to use @@ -160,7 +160,7 @@ DeclareAttribute("RecogDecompinfoHomomorphism",IsMapping,"mutable"); ## ## For a finite group G, for which ## ffs has been computed, -## this function returns a subgroup U build from data compatible with +## this function returns a subgroup U built from data compatible with ## ffs: U is the subgroup generated by gens and ## ipcgs. ## ipcgs is an induced Pcgs for U\cap Rad(G), with respect to diff --git a/lib/fitfree.gi b/lib/fitfree.gi index e8669473c0..31b71a4982 100644 --- a/lib/fitfree.gi +++ b/lib/fitfree.gi @@ -730,7 +730,7 @@ local stabilizergen,st,stabrsub,stabrsubsz,ratio,subsz,sz,vp,stabrad, #if IsBound(reps[vp+j]) then # Add(reps,reps[vp+j]*gens[genum]); #fi; - # repwordslso needs to change! + # repwords also needs to change! Add(repwords,Concatenation(repwords[vp+j],[genum])); b[p]:=true; od; @@ -1542,7 +1542,7 @@ local ff,i,j,c,q,a,b,prev,sub,m,k; a:=LinearActionLayer(G,m); a:=GModuleByMats(a,GF(RelativeOrders(m)[1])); b:=MTX.BasesSubmodules(a); - b:=b{[2..Length(b)-1]}; # only intermnediate ones + b:=b{[2..Length(b)-1]}; # only intermediate ones if Length(b)>0 then for j in Reversed(b) do Add(c,ClosureSubgroupNC(k,List(j,x->PcElementByExponents(m,x)))); diff --git a/lib/galois.gd b/lib/galois.gd index 4cb7e1e1fe..16f4767269 100644 --- a/lib/galois.gd +++ b/lib/galois.gd @@ -47,7 +47,7 @@ DeclareInfoClass("InfoGalois"); ## cases the required calculations become unfeasibly large. ##

## For a few polynomials of degree 14, a complete discrimination is not yet -## possible, as it would require computations, that are not feasible with +## possible, as it would require computations that are not feasible with ## current factoring methods. ##

## This function requires the transitive groups library to be installed (see diff --git a/lib/galois.gi b/lib/galois.gi index 7303d0065d..ed764709b7 100644 --- a/lib/galois.gi +++ b/lib/galois.gi @@ -393,12 +393,12 @@ local i,p,r,x,d; IndeterminateNumberOfUnivariateRationalFunction(f)); # remember, which resolvent types already failed (most likely for # smaller sums), so we won't have to use them twice! - # e.g.: if 2-Sum is double, then 3-Sum will vbe double most likely! + # e.g.: if 2-Sum is double, then 3-Sum will be double most likely! if not IsBound(f!.failedResolvents) then f!.failedResolvents:=[]; fi; if Value(f,-x)=f then - # then for every root there is a negative one, causing trobles with sums + # then for every root there is a negative one, causing troubles with sums f!.failedResolvents:=Union(f!.failedResolvents,[0,1,2]); fi; i:=0; diff --git a/lib/ghom.gd b/lib/ghom.gd index 59857eade4..1f2d404282 100644 --- a/lib/ghom.gd +++ b/lib/ghom.gd @@ -235,8 +235,8 @@ DeclareRepresentation( "IsGroupGeneralMappingByAsGroupGeneralMappingByImages", ## ## ## If map is a mapping from one group to another this attribute -## returns a group general mapping that which implements the same abstract -## mapping. (Some operations can be performed more effective in this +## returns a group general mapping that implements the same abstract +## mapping. (Some operations can be performed more effectively in this ## representation, see ## also .) ## ## ## -## returns an augmented coset table for an homomorphism from an fp group, +## returns an augmented coset table for a homomorphism from an fp group, ## corresponding to the !.generators component. The component ## .secondaryImages of this table will give the images of all (primary ## and secondary) subgroup generators under hom. @@ -348,7 +348,7 @@ DeclareGlobalFunction("LargerQuotientBySubgroupAbelianization"); ## form of G itself being a permutation/matrix or fp group. It also can ## be if G is finitely presented but (its family) has an ## FPFaithHom. (However it will not apply if G is a subgroup -## of an fp group.) The result of this is make higher level calculations in +## of an fp group.) The result of this is to make higher level calculations in ## F more efficient. ## This is an internal function that does not test its arguments and the ## result is undefined if calling the function on any other object. diff --git a/lib/ghomfp.gi b/lib/ghomfp.gi index 7c2f3d4d0c..2f0a940031 100644 --- a/lib/ghomfp.gi +++ b/lib/ghomfp.gi @@ -173,7 +173,7 @@ local si,sw,i,ug,tt,p; if p<>fail then Add(si,aug.homgenims[p]); else - # its not. We must map the image from the primary generators images. + # it's not. We must map the image from the primary generators images. # For this we use that their images must be given already in `si', as # the primary generators come first. Add(si,MappedWord(tt[i],aug.primarySubgroupGenerators, @@ -1009,7 +1009,7 @@ end ); #M Tietze transformations ## ## `SimplifiedFpGroup' returns a group isomorphic to the given one with a -## presentation which has been tried to simplify via Tietze transformations. +## presentation which we have tried to simplify via Tietze transformations. ## InstallGlobalFunction( SimplifiedFpGroup, function ( G ) return Range(IsomorphismSimplifiedFpGroup(G:easy)); diff --git a/lib/ghompcgs.gi b/lib/ghompcgs.gi index 716721c710..354ba112b9 100644 --- a/lib/ghompcgs.gi +++ b/lib/ghompcgs.gi @@ -96,7 +96,7 @@ InstallMethod( CompositionMapping2, "method for two pc group automorphisms", function( hom1, hom2 ) local fam,hom, pcgs, pcgsimgs, G; - # is it automorphism? + # is it an automorphism? if Range(hom1)<>Source(hom2) then TryNextMethod(); fi; @@ -288,7 +288,7 @@ BindGlobal( "InversePcgs", function( hom ) # if it is known then return if IsBound( hom!.rangePcgs ) then return; fi; - # if it is from an pc group + # if it is from a pc group if IsBound( hom!.sourcePcgs ) then idR := Identity( Range( hom ) ); diff --git a/lib/gpprmsya.gi b/lib/gpprmsya.gi index d0af65692e..72b65a64ba 100644 --- a/lib/gpprmsya.gi +++ b/lib/gpprmsya.gi @@ -2074,7 +2074,7 @@ local a,b,x,i; end); # maximal subgroups routine. -# precomputed data up to degree 50 (so it will be quick is most cases). +# precomputed data up to degree 50 (so it will be quick in most cases). # (As there is no independent check for the primitive groups of degree >50, # we rather do not refer to them, but only use them in a calculation.) BindGlobal("SNMAXPRIMS", MakeImmutable([[],[],[],[],[],[2],[],[5],[],[7],[],[4], diff --git a/lib/groebner.gd b/lib/groebner.gd index 9a96b84ad1..eecc4aea10 100644 --- a/lib/groebner.gd +++ b/lib/groebner.gd @@ -346,7 +346,7 @@ DeclareGlobalFunction("MonomialGrevlexOrdering"); ## Two monomials are compared first by the exponent vectors for the ## variables listed in elim (a lexicographic comparison with respect ## to the ordering indicated in elim). -## If these submonomial are equal, the submonomials given by the other +## If these submonomials are equal, the submonomials given by the other ## variables are compared by a graded lexicographic ordering ## (with respect to the variable order given in rest, ## if called with two parameters). @@ -428,7 +428,7 @@ DeclareGlobalFunction("PolynomialReduction"); ## ## ## -## this operation does the same way as +## this operation works the same way as ## but does not keep track of the actual quotients ## and returns only the remainder (it is therefore slightly faster). ## diff --git a/lib/groebner.gi b/lib/groebner.gi index abe76319ed..b0c26cd142 100644 --- a/lib/groebner.gi +++ b/lib/groebner.gi @@ -222,7 +222,7 @@ InstallMonomialOrdering(MonomialLexOrdering, # b has no variable as large as am. thus a is bigger return false; elif ret<>fail then - # b has no larger variable than am buty has am. Use the comparison + # b has no larger variable than am but has am. Use the comparison return ret; fi; min:=am; # will increase until no variable in a left @@ -367,7 +367,7 @@ InstallMonomialOrdering(MonomialGrlexOrdering, # b has no variable as large as am. thus a is bigger return false; elif ret<>fail then - # b has no larger variable than am buty has am. Use the comparison + # b has no larger variable than am but has am. Use the comparison return ret; fi; min:=am; # will increase until no variable in a left @@ -664,7 +664,7 @@ local fam,quot,elist,lmp,lmo,lmc,x,y,z,mon,mon2,qmon,noreduce, #divides and there is remainder Append(qmon,[mon[pos],di]); elif di<0 then - noreduce:=true; # exponent to small + noreduce:=true; # exponent too small fi; pos:=pos+2; z:=z+2; @@ -762,7 +762,7 @@ local fam, elist, lmp, lmo, lmc, ep, rem, noreduce, x, mon, y, mon2, #divides and there is remainder Append(qmon,[mon[pos],di]); elif di<0 then - noreduce:=true; # exponent to small + noreduce:=true; # exponent too small fi; pos:=pos+2; z:=z+2; @@ -851,7 +851,7 @@ local fam,quot,elist,lmp,lmo,lmc,x,y,z,mon,mon2,qmon,noreduce, #divides and there is remainder Append(qmon,[mon[pos],di]); elif di<0 then - noreduce:=true; # exponent to small + noreduce:=true; # exponent too small fi; pos:=pos+2; z:=z+2; diff --git a/lib/grpcompl.gi b/lib/grpcompl.gi index 5058cd8610..df3ef8187d 100644 --- a/lib/grpcompl.gi +++ b/lib/grpcompl.gi @@ -87,7 +87,7 @@ local G,N,K,s, h, q, fpi, factorpres, com, comgens, cen, ocrels, fpcgs, ncom, # construct a presentation h:=NaturalHomomorphismByNormalSubgroup(G,N); - # AH still: Try to find a more simple presentation if available. + # AH still: Try to find a simpler presentation if available. if Source(h)=G then q:=ImagesSource(h); diff --git a/lib/grpfp.gi b/lib/grpfp.gi index 414ee482c8..4434ecd3f9 100644 --- a/lib/grpfp.gi +++ b/lib/grpfp.gi @@ -810,7 +810,7 @@ BindGlobal("HasFullColumnRankIntMatDestructive",function( mat ) fi; od; if rbx{r}); @@ -1030,7 +1030,7 @@ end ); #M do a coset enumeration ## ## 'CosetTableFromGensAndRels' is the workhorse for computing a coset -## table of H in G where G is a finitley presented group, H is a subgroup of +## table of H in G where G is a finitely presented group, H is a subgroup of ## G, and G is the whole group of H. It applies a Felsch strategy Todd- ## Coxeter coset enumeration. The expected parameters are ## @@ -1049,7 +1049,7 @@ end ); ## enumeration does not finish with this number of cosets, an error is ## raised and the user is asked whether she wants to continue ## -## `silent' & if set to `true' the algorithm will not rais the error +## `silent' & if set to `true' the algorithm will not raise the error ## mentioned under option `max' but silently return `fail'. This can be ## useful if an enumeration is only wanted unless it becomes too big. ## \enditems @@ -1901,7 +1901,7 @@ function ( G, H ) return G; fi; - # its worth to check inclusion first + # it's worth checking inclusion first if IndexInWholeGroup(G)<=IndexInWholeGroup(H) and IsSubset(G,H) then return H; elif IndexInWholeGroup(H)<=IndexInWholeGroup(G) and IsSubset(H,G) then @@ -1976,7 +1976,7 @@ InstallMethod(Intersection2,"subgroups of fp group by quotient",IsIdenticalObj, function ( G, H ) local d,A,B,e1,e2,Ag,Bg,s,sg,u,v,map,sz; - # it is not worth to check inclusion first since we're reducing afterwards + # it is not worth checking inclusion first since we're reducing afterwards #if IndexInWholeGroup(G)<=IndexInWholeGroup(H) and IsSubset(G,H) then # return H; #elif IndexInWholeGroup(H)<=IndexInWholeGroup(G) and IsSubset(H,G) then @@ -3953,7 +3953,7 @@ InstallMethod(Size, "for finitely presented groups", true, ############################################################################# ## -#M Size( ) . . . . . . size of s subgroup of a finitely presented group +#M Size( ) . . . . . . size of a subgroup of a finitely presented group ## InstallMethod(Size,"subgroups of finitely presented groups",true, [ IsSubgroupFpGroup ], 0, diff --git a/lib/grplatt.gd b/lib/grplatt.gd index 857a23c853..6b0d0dffb4 100644 --- a/lib/grplatt.gd +++ b/lib/grplatt.gd @@ -8,7 +8,7 @@ ## ## SPDX-License-Identifier: GPL-2.0-or-later ## -## This file contains declarations for subgroup latices +## This file contains declarations for subgroup lattices ## @@ -436,7 +436,7 @@ DeclareGlobalFunction("TomDataSubgroupsAlmostSimple"); ## obtained as lim-fold iterated maximal subgroups. ## ## If a function cond is given, only subgroups for which this -## function returns true (also for their intermediate overgroups) is +## function returns true (also for their intermediate overgroups) are ## returned. If also a function dosub is given, maximal subgroups ## are only attempted if this function returns true (this is separated for ## performance reasons). diff --git a/lib/grplatt.gi b/lib/grplatt.gi index 7419486e85..eaeb9714ec 100644 --- a/lib/grplatt.gi +++ b/lib/grplatt.gi @@ -2346,9 +2346,9 @@ local n,i,s; if Size(G)=1 then return G;fi; # force an IsNilpotent check - # should have and IsSolvable check, as well, + # should have an IsSolvable check, as well, # but methods for solvable groups are only in CRISP - # which aggeressively checks for solvability, anyway + # which aggressively checks for solvability, anyway if (not HasIsNilpotentGroup(G) and IsNilpotentGroup(G)) then return Socle(G); fi; @@ -2395,7 +2395,7 @@ local rt,op,a,l,i,j,u,max,subs; # compute inclusion information among sets SortBy(a, Length); - # this is n^2 but I hope will not dominate everything. + # this is n^2 but I hope it will not dominate everything. subs:=List([1..l],i->Filtered([1..i-1],j->IsSubset(a[i],a[j]))); # List the sets we know to be contained in each set diff --git a/lib/grppccom.gi b/lib/grppccom.gi index bb59eef42e..74229971ae 100644 --- a/lib/grppccom.gi +++ b/lib/grppccom.gi @@ -139,7 +139,7 @@ local tau, phi, mats; # Get the matrices describing the affine operations. The linear part # of the operation is just conjugation of the entries of cocycle. The - # translation are commuators with the generators. So check if + # translations are commutators with the generators. So check if # has a small generating set. Use only these to form the commutators. # Translation: (.. h ..) -> (.. [h,c] ..) @@ -1066,7 +1066,7 @@ local G,N,M,keep,H,K,f,primes,p,A,S,L,hom,c,cn,nc,ncn,lnc,lncn,q,qs,qn,ser, genpos:=PositionProperty(acterlist,x->a=x[1]); if genpos=fail then if IsOne(a) then - # the action test always does the identity, so its worth + # the action test always does the identity, so it's worth # catching this as we have many short orbits return cy; else diff --git a/lib/grppclat.gd b/lib/grppclat.gd index d2caeac101..859d934de7 100644 --- a/lib/grppclat.gd +++ b/lib/grppclat.gd @@ -147,7 +147,7 @@ DeclareGlobalFunction( ## elementary abelian subgroup G of P. Returns ## a list [subspaces,action], where subspaces is a list of all the ## subspaces and action a homomorphism from P in a permutation group, -## which is equal to the action homomrophism for the action of P on +## which is equal to the action homomorphism for the action of P on ## subspaces. If dims is given, only subspaces of dimension dims are ## considered. ## diff --git a/lib/grppclat.gi b/lib/grppclat.gi index b313ba6359..28db0a7278 100644 --- a/lib/grppclat.gi +++ b/lib/grppclat.gi @@ -42,7 +42,7 @@ local G,morph,N,s,p,e,i,j,k,ise,fine,cor; i:=2; while i<=Length(e) do # intersect all images of normal subgroup to obtain invariant one - # as G is invariant, we dont have to deal with special cases + # as G is invariant, we don't have to deal with special cases ise:=[e[i]]; cor:=e[i]; for j in ise do @@ -254,7 +254,7 @@ end); ## elementary abelian subgroup of

. Returns ## a list [,], where is a list of all the ## subspaces (as groups) and a homomorphism from

in a -## permutation group, which is equal to the action homomrophism for the +## permutation group, which is equal to the action homomorphism for the ## action of

on . If is given, only subspaces of ## dimension are considered. Instead of also a (modulo) pcgs ## may be given, in this case are pre-images of the subspaces. @@ -659,7 +659,7 @@ local g, # group fi; fi; -# # check, if the series is compatible with the AgSeries and if g is a +# # check if the series is compatible with the AgSeries and if g is a # # parent group. If not, enforce this # if not(IsParent(g) and ForAll(e,IsElementAgSeries)) then # Info(InfoPcSubgroup,1," computing better series"); @@ -888,14 +888,14 @@ Assert(1,ForAll(bs,i->ForAll(efunc,j->Image(j,i)=i))); for bpos in [1..Length(bs)] do b:=bs[bpos]; Assert(2,IsNormal(a,b)); - # test, whether we'll have to consider this case + # test whether we'll have to consider this case # this test has basically be done before the orbit calculation already # if consider<>false and consider(a,n,b,e[i])=false then # Info(InfoPcSubgroup,2," Ignoring case"); # s:=[]; - # test, whether b is invariant + # test whether b is invariant if Length(efunc)>0 then # extend to dcs of bnormalizer s:=RightTransversal(no,bsnorms[bpos]); @@ -903,7 +903,7 @@ Assert(1,ForAll(bs,i->ForAll(efunc,j->Image(j,i)=i))); s:=Concatenation(List(s,i->List(t,j->i*j))); z:=Length(s); #NOCH: Fusion - # test, which ones are usable at all + # test which ones are usable at all s:=Filtered(s,i->HasInvariantConjugateSubgroup(b,i,efunc)); Info(InfoPcSubgroup,2," |s|=",nag,"-(m)>",z,"-(i)>",Length(s)); else diff --git a/lib/grpreps.gi b/lib/grpreps.gi index 4a317738e9..1d1c0b7c3a 100644 --- a/lib/grpreps.gi +++ b/lib/grpreps.gi @@ -58,7 +58,7 @@ local modu, modus,gens,v,subs,sub,ser,i,j,a,si,dims,cf,mats,clos,bas,rad; elif IsAbelian(G) then if IsPrimeField(F) then if CanEasilyComputePcgs(G) then - # call `IrreducibleMethods` again; + # call `IrreducibleModules` again; # we assume that now another method is applicable return IrreducibleModules(G, F, 1); else diff --git a/lib/matint.gd b/lib/matint.gd index bf266593c1..4873ae2924 100644 --- a/lib/matint.gd +++ b/lib/matint.gd @@ -109,7 +109,7 @@ DeclareSynonym("TriangulizedIntegerMatTransforms", ## ## ## This operation computes the Hermite normal form of a matrix mat -## with integer entries. It returns a immutable matrix in HNF. +## with integer entries. It returns an immutable matrix in HNF. ## ## ## <#/GAPDoc> diff --git a/lib/matint.gi b/lib/matint.gi index 167acc62ba..a1b01a67b0 100644 --- a/lib/matint.gi +++ b/lib/matint.gi @@ -902,7 +902,7 @@ local sig, n, m, A, r, c2, c1, j, k, c, i, g, q; #Embed mat in 2 larger "id" matrix n := Length(mat)+2; - # Crossover point roughly 20x20 matrices, so farm the work if smaller.. + # Crossover point roughly 20x20 matrices, so farm the work out if smaller.. if n<22 then return DeterminantMat(mat);fi; m := NrCols(mat)+2; @@ -1049,7 +1049,7 @@ local n,zero,nv,new,pip,piv,i,v,p,w,g,pin,now,rat,extra,clean,assign,try; mat:=[]; extra:=[]; - # we once reduce and then go over the remainders again in case they were + # we reduce once and then go over the remainders again in case they were # nice and short for try in [1..3] do SortBy(new, x -> - x*x); # reversed norm sort diff --git a/lib/matrix.gd b/lib/matrix.gd index 31ddbf47fb..8e29b58c35 100644 --- a/lib/matrix.gd +++ b/lib/matrix.gd @@ -2430,7 +2430,7 @@ DeclareOperation("FieldOfMatrixList",[IsListOrCollection]); ## R such that all entries of the matrices lie in R. If ## R has a quotient field that can be represented, this quotient ## field is returned instead. -## In general R is not chosen to be as small as possible, but to +## In general R is not chosen to be as small as possible, but to ## be determined quickly without being unnecessarily large ## (see ). ## diff --git a/lib/maxsub.gi b/lib/maxsub.gi index c69f873028..54ef8dcd93 100644 --- a/lib/maxsub.gi +++ b/lib/maxsub.gi @@ -368,7 +368,7 @@ local c, maxs,sel,reps; reps:=reps{sel}; SortBy(reps, Size); - # nor go by descending order through the representatives. Always eliminate + # now go by descending order through the representatives. Always eliminate # all remaining proper subgroups of conjugates. What remains must be # maximal. maxs:=[]; diff --git a/lib/meatauto.gi b/lib/meatauto.gi index b7cf1e1862..e4488bb90e 100644 --- a/lib/meatauto.gi +++ b/lib/meatauto.gi @@ -394,7 +394,7 @@ local V, nv, W, nw, U, echu, F, matsV, matsW, k, g1, g2, max_stack_len, _t, fi; od; if extradim[i] > 0 then - # exit early if we have found an element that gets use all + # exit early if we have found an element that gets us all # of after spinning done:=extradim[i] = nv - Length(U); if done then @@ -519,7 +519,7 @@ local nv, nw, F, zero, minusone, zeroW, gV, gW, k, U, echu, r, homs, s, work, an # then computes Hom(U',W) for U' a submodule generated by and a # single element in . This U' becomes the next as the process # is iterated, ending when = . The element is chosen in a -# nullspace of a group algebra element in order to restrict it possible +# nullspace of a group algebra element in order to restrict its possible # images in . nv:=V.dimension; @@ -958,7 +958,7 @@ local proveIndecomposability, addnilpotent, n, F, zero, basis, enddim, # We will "quotient" out the nilpotent subspace as we go. The elements # of remain tell us which (echelonised) basis elements of the - # endomorphism algebra we will take use in our random linear + # endomorphism algebra we will use in our random linear # combination. # remain:=[1..enddim]; @@ -995,7 +995,7 @@ local proveIndecomposability, addnilpotent, n, F, zero, basis, enddim, fi; # Compute the order polynomial of `a` with respect to a random vector, - # i.e., a (cheap) factor of the minimal polynomial, then pick the any + # i.e., a (cheap) factor of the minimal polynomial, then pick any # factor of that (in practice, we pick one with minimal degree for # efficiency) and evaluate it at a. The resulting matrix will be # non-zero and non-regular, giving us a chance to find a splitting in diff --git a/lib/meataxe.gd b/lib/meataxe.gd index 45e85af487..7fa602c604 100644 --- a/lib/meataxe.gd +++ b/lib/meataxe.gd @@ -78,7 +78,7 @@ DeclareGlobalFunction("DirectSumGModule"); #F WedgeGModule ( module ) . . . . . wedge product of a G-module ## ## WedgeGModule calculates the wedge product of a G-module. -## That is the action on antisymmetrix tensors. +## That is the action on antisymmetric tensors. ## DeclareGlobalFunction("WedgeGModule"); diff --git a/lib/meataxe.gi b/lib/meataxe.gi index a64617518e..49acc2c897 100644 --- a/lib/meataxe.gi +++ b/lib/meataxe.gi @@ -206,7 +206,7 @@ end); #F WedgeGModule( module ) . . . . . wedge product of a G-module ## ## WedgeGModule calculates the wedge product of a G-module. -## That is the action on antisymmetrix tensors. +## That is the action on antisymmetric tensors. ## InstallGlobalFunction(WedgeGModule, function(module) local mats, mat, newmat, row, F, gens, dim, nmats, i, j, k, m, n, x; @@ -335,7 +335,7 @@ SMTX.SetDegreeFieldExt:=SMTX.Setter("degreeFieldExt"); ############################################################################# ## -#F SMTX.OrthogonalVector( subbasis ) single vector othogonal to a submodule, +#F SMTX.OrthogonalVector( subbasis ) single vector orthogonal to a submodule, ## N.B. subbasis is assumed to consist of normed vectors, ## submodule is assumed proper. ## @@ -786,7 +786,7 @@ end; ## where smodule is the submodule and qmodule the quotient module. ## The matrices of nmodule have the form A 0 where A and B are the ## C B -## corresponding matrices of smodule and qmodule resepctively. +## corresponding matrices of smodule and qmodule respectively. ## If sub is not the basis of a submodule then fail is returned. SMTX.InducedAction:=function(module, sub, typ...) local ans,erg; @@ -1391,7 +1391,7 @@ local matrices, M, mat, N, newgenlist, coefflist, Info(InfoMeatAxe,4,"Evaluated characteristic polynomial. Time = ", Runtime()-rt0,"."); - # That is necessary in case p is defined over a smaller field that F. + # That is necessary in case p is defined over a smaller field than F. oldpol:=pol; # Now we extract the irreducible factors of pol starting with those # of low degree @@ -2094,7 +2094,7 @@ SMTX.Distinguish:=function(cf, i) # First evaluate on cf[i][1]. M:=ImmutableMatrix(F,Sum([1..ngens], k -> el[2][k] * matsi[k])); p:=CharacteristicPolynomialMatrixNC(F,M,1); - # That is necessary in case p is defined over a smaller field that F. + # That is necessary in case p is defined over a smaller field than F. oldp:=p; # extract irreducible factors deg:=0; @@ -3114,7 +3114,7 @@ end; ## #F BasisInOrbit( module ) . . . . ## -## Find a basis of the irrecucible GModule module that is contained in +## Find a basis of the irreducible GModule module that is contained in ## an orbit of the action of G. ## The code is similar to that of SpinnedBasis. SMTX.BasisInOrbit:=function(module) diff --git a/lib/morpheus.gd b/lib/morpheus.gd index 32dae42370..3440f7b0fb 100644 --- a/lib/morpheus.gd +++ b/lib/morpheus.gd @@ -410,7 +410,7 @@ DeclareGlobalFunction("MorClassLoop"); ## ## ## tries to find generating system with as few as possible generators -## which will be taken preferraby from the first classes in cl +## which will be taken preferably from the first classes in cl ## ## ## @@ -429,7 +429,7 @@ DeclareGlobalFunction("MorFindGeneratingSystem"); ## isomorphisms between G and H or the automorphism group of G (in which ## case G must equal H). The boolean flag DoAuto indicates if all ## automorphisms should be found. -## The function requires, that both groups are not cyclic! +## The function requires that both groups are not cyclic! ## ## ## diff --git a/lib/morpheus.gi b/lib/morpheus.gi index 2dacd6e8a4..27d8faca23 100644 --- a/lib/morpheus.gi +++ b/lib/morpheus.gi @@ -21,7 +21,7 @@ MORPHEUSELMS := 50000; # orders of group elements in factors of this series under action of `hom`. # Every time an orbit length is found, `hom` is replaced by the appropriate # power. Initially small chief factors are preferred. In the end all -# generators are used while stepping through the series descendingly, thus +# generators are used while stepping through the series in descending order, thus # ensuring the proper order is found. InstallMethod(Order,"for automorphisms",true,[IsGroupHomomorphism],0, function(hom) @@ -123,7 +123,7 @@ local map,phi,o,lo,i,j,start,img,d,nat,ser,jord,first; od; od; - # if iterating make `jord` standard to we don't skip generators + # if iterating make `jord` standard so we don't skip generators jord:=[2..Length(ser)]; first:=false; od; @@ -423,7 +423,7 @@ local hom, gens, c, ran, r, cen, img, u, orbs, finish(hom); return; fi; - # if no centre and all automorphism conjugator, try to extend exiting permrep + # if no centre and all automorphism conjugator, try to extend existing permrep if Size(Centre(g))=1 and IsPermGroup(g) and ForAll(GeneratorsOfGroup(au),IsConjugatorAutomorphism) then ran:= Group( List( GeneratorsOfGroup( au ), @@ -449,7 +449,7 @@ local hom, gens, c, ran, r, cen, img, u, orbs, if not img in ran then # There is still something centralizing left. if not img in r then - # get the cenralizing bit + # get the centralizing bit r:=ClosureGroup(r,img); cen:=Centralizer(r,g); fi; @@ -1712,7 +1712,7 @@ end); ############################################################################# ## #F MorFindGeneratingSystem(,) . . find generating system with as few -## as possible generators from the first classes in +## generators as possible from the first classes in ## InstallGlobalFunction(MorFindGeneratingSystem,function(arg) local G,cl,lcl,len,comb,combc,com,a,alltwo; @@ -1754,10 +1754,10 @@ end); ## #F Morphium(,,) . . . . . . . .Find isomorphisms between G and H ## modulo inner automorphisms. DoAuto indicates whether all -## automorphism are to be found +## automorphisms are to be found ## This function thus does the main combinatoric work for creating ## Iso- and Automorphisms. -## It needs, that both groups are not cyclic. +## It requires that both groups are not cyclic. ## InstallGlobalFunction(Morphium,function(G,H,DoAuto) local combi,Gr,Gcl,Ggc,Hr,Hcl,bg,bpri,x,dat, @@ -1837,7 +1837,7 @@ local combi,Gr,Gcl,Ggc,Hr,Hcl,bg,bpri,x,dat, return []; fi; - # now test, whether it is worth, to compute a finer congruence + # now test whether it is worth computing a finer congruence # then ALSO COMPUTE NEW GEN SYST! # [...] @@ -2442,7 +2442,7 @@ InstallGlobalFunction(AutomorphismGroupFittingFree,function(g) # get a set of elements that uniquely describes the point p s:=SmallGeneratingSet(Stabilizer(ge,p)); if ForAny(Difference(i,[p]),j->ForAll(s,x->j^x=j)) then - # try once more -- there is some randomeness involved + # try once more -- there is some randomness involved if count<10 then return AutomorphismGroupFittingFree(g:count:=count+1); fi; @@ -2490,7 +2490,7 @@ end); InstallMethod(AutomorphismGroup,"finite groups",true,[IsGroup and IsFinite],0, function(G) local A; - # since the computation is expensive, it is worth to test some properties first, + # since the computation is expensive, it is worth testing some properties first, # instead of relying on the method selection if IsAbelian(G) then A:=AutomorphismGroupAbelianGroup(G); @@ -3001,7 +3001,7 @@ local Fgens, # generators of F fak, # multiplication factor cnt; # countdown for finish - # if we have a pontentially infinite fp group we cannot be clever + # if we have a potentially infinite fp group we cannot be clever if IsSubgroupFpGroup(F) and (not HasSize(F) or Size(F)=infinity) then TryNextMethod(); diff --git a/lib/onecohom.gi b/lib/onecohom.gi index e1432730e3..f7d0f93ec1 100644 --- a/lib/onecohom.gi +++ b/lib/onecohom.gi @@ -213,9 +213,9 @@ InstallGlobalFunction(OCAddGenerators,function(ocr,G) ocr.generatorsAdded:=true; # though using the method selection would be nicer,here the decisions are - # that involved we actually have to use a dispatcher + # so involved that we actually have to use a dispatcher if IsBound(ocr.inPcComplement) # the pc complement routines interface - # directly,giving generators that form an + # directly,giving generators that form a # pcgs or ((IsPcGroup(G) or (IsBound(ocr.generators) and IsGeneralPcgs(ocr.generators))) @@ -368,7 +368,7 @@ local base, dim, gens; end; else - # Get the correcting list. The nongenerator correction are given + # Get the correcting list. The nongenerator corrections are given # by m_i + n_1*C_ij+... for i a nongenerator index and j a # generator index. m_i is stored inand C_ij is # stored in. @@ -859,7 +859,7 @@ local mat, i, j, v, vv; od; od; - # if has an entry 'conjugated' the records is no relator for a + # if has an entry 'conjugated' the record is not a relator for a # presentation,but belongs to relation # (g_i n_i)^s_j = r # which is used to determinate normal complements. [i,j] is bound to @@ -994,7 +994,7 @@ local mat, i, j, v, vv; od; od; - # If has an entry the records is no relator for a + # If has an entry the record is not a relator for a # presentation,but belongs to relation # (g_i n_i)^s_j = # which is used to determinate normal complements. [i,j] is bound to @@ -1015,7 +1015,7 @@ end); InstallGlobalFunction(OCEquationVector,function(ocr,r) local n,i; - # If has an entry 'conjugated' the records is no relator for a + # If has an entry 'conjugated' the record is not a relator for a # presentation,but belongs to relation # (g_i n_i)^s_j = # which is used to determinate normal complements. [i,j] is bound to @@ -1045,7 +1045,7 @@ end); InstallGlobalFunction(OCSmallEquationVector,function(ocr,r) local n, a, i, nonSmall, v, vv, j; - # ifhas an entry 'conjugated' the records is no relator for a + # ifhas an entry 'conjugated' the record is not a relator for a # presentation,but belongs to relation # (g_i n_i)^s_j = # which is used to determinate normal complements. [i,j] is bound to @@ -1136,7 +1136,7 @@ end); ## #F OCOneCocycles(,) . . . . . . one cocycles main routine ## -## If,'OCOneCocycles' returns 'false' as soon as possibly if +## If,'OCOneCocycles' returns 'false' as soon as possible if ## the extension does not split. ## InstallGlobalFunction(OCOneCocycles,function(ocr,onlySplit) @@ -1170,7 +1170,7 @@ local cobounds,cocycles, # base of one coboundaries and cocycles # matrices and vectors. cobounds:=BasisVectors(Basis(OCOneCoboundaries(ocr))); - # If we are only want normal complements,the group of cobounds must be + # If we only want normal complements,the group of cobounds must be # trivial, otherwise there are no normal ones as the conjugated # complements correspond with the cobounds. if IsBound(ocr.normalIn) and cobounds<>[] then @@ -1187,7 +1187,7 @@ local cobounds,cocycles, # base of one coboundaries and cocycles OCAddBigMatrices(ocr,ocr.generators); fi; - # Now initialize a matrix with will hold the triangulized system of + # Now initialize a matrix which will hold the triangulized system of # linear equations. If 'smallGeneratingSet' is given use this, if # 'pPrimeSet' is given do not use those. dim:=Length(ocr.modulePcgs); @@ -1248,7 +1248,7 @@ local cobounds,cocycles, # base of one coboundaries and cocycles fi; - # The is a system for x M = v so transpose. + # This is a system for x M = v so transpose. RS:=MutableTransposedMat(RS); # Now append this to the triangulized system. @@ -1280,7 +1280,7 @@ local cobounds,cocycles, # base of one coboundaries and cocycles od; # Now remove all entries above the diagonal. Let's see if a solution - # exist. As system is triangulized all we have to do,is to check if + # exists. As system is triangulized all we have to do,is to check if # right side is null,where the diagonal is null. Info(InfoCoh,2,"OCOneCocycles: computing nullspace and solution"); for i in [1 .. Length(S)] do diff --git a/lib/oprtglat.gd b/lib/oprtglat.gd index c5bce4e371..1ca87defdd 100644 --- a/lib/oprtglat.gd +++ b/lib/oprtglat.gd @@ -40,7 +40,7 @@ DeclareGlobalFunction("MinimumGroupOnSubgroupsOrbit"); #O PermPreConjtestGroups(G,l) ## ## Utility function: Cluster permgroups according to orbits and cycle -## structures, possibly conjugating. This is only worth if there are many +## structures, possibly conjugating. This is only worthwhile if there are many ## very similar subgroups and thus not part of the default ## SubgroupsOrbitsAndNormalizers method. DeclareGlobalFunction("PermPreConjtestGroups"); diff --git a/lib/oprtglat.gi b/lib/oprtglat.gi index 43b4531805..deba2ddf15 100644 --- a/lib/oprtglat.gi +++ b/lib/oprtglat.gi @@ -130,7 +130,7 @@ end); # if groups are fully conjugated) # gps (groups already conjugates so the action is reduced to acts for each # cluster) -# conjugators (for subgroups in list, elements conjugationg to gps) +# conjugators (for subgroups in list, elements conjugating to gps) # normalizers: if not `false` normalizers of cluster rep in gps # diff --git a/lib/permdeco.gd b/lib/permdeco.gd index b6c0e440a0..55342a5275 100644 --- a/lib/permdeco.gd +++ b/lib/permdeco.gd @@ -21,18 +21,18 @@ ## . This function returns a permutation group $H$, isomorphic to $G$, ## such that all the automorphisms in can be represented by ## conjugation of $H$ with elements of the symmetric group. It returns a -## list $[H2,\phi,a]$ where $\phi is the isomorphism $G\to H$, and $a$ a +## list $[H2,\phi,a]$ where $\phi$ is the isomorphism $G\to H$, and $a$ a ## list of permutations corresponding to that induce the same ## automorphisms of $H$. Finally $H2=\left\langle H,a\right\rangle$. ## The algorithm may fail if is not almost simple. -## The group $H$ is guaranteed to act on points [1..n] without fixedpoints. +## The group $H$ is guaranteed to act on points [1..n] without fixed points. DeclareGlobalFunction("AutomorphismRepresentingGroup"); ############################################################################# ## #F EmbedAutomorphisms(,,,[,]) ## -## Suposet that $GT$ and $HT$ are isomorphic simple groups and $GT\le +## Suppose that $GT$ and $HT$ are isomorphic simple groups and $GT\le ## G\le\Aut(GT)$ and $HT\le H\le \Aut(HT)$. This function returns a new ## group $P$ isomorphic to a subgroup of $\Aut(GT)$ and monomorphisms ## $\phi\colon G\to P$ and $\psi\colon H\to P$ in the form of a list diff --git a/lib/permdeco.gi b/lib/permdeco.gi index e605798c0f..9b6ae8d4b3 100644 --- a/lib/permdeco.gi +++ b/lib/permdeco.gi @@ -269,7 +269,7 @@ local tryrep,sel,selin,a,s,dom,iso,stabs,outs,map,i,j,p,found,seln, fi; # test the automorphisms that are not inner. (The conjugator automorphisms - # have no reason to be normal in all automoirphisms, so this will not + # have no reason to be normal in all automorphisms, so this will not # work.) seln:=Filtered(sel,x->not IsInnerAutomorphism(autos[x])); diff --git a/lib/polyfinf.gd b/lib/polyfinf.gd index 66d370e0f0..5e295fb7b4 100644 --- a/lib/polyfinf.gd +++ b/lib/polyfinf.gd @@ -34,7 +34,7 @@ DeclareGlobalFunction("RootsRepresentativeFFPol"); ## ## Computes an integer n such that OnSets( , n ) contains only one ## element e. must be a list of prime powers of an integer d such that -## n divides d. The functions returns the integer n and the element e. +## n divides d. The function returns the integer n and the element e. ## DeclareGlobalFunction("OrderKnownDividendList"); @@ -43,8 +43,8 @@ DeclareGlobalFunction("OrderKnownDividendList"); #F FFPOrderKnownDividend( , , , ) . . . . . . . . . . . local ## ## Computes an integer n such that ^n = const mod where and -## are polynomials in and is list of prime powers of an integer d -## such that n divides d. The functions returns the integer n and the +## are polynomials in and is a list of prime powers of an integer d +## such that n divides d. The function returns the integer n and the ## element const. DeclareGlobalFunction("FFPOrderKnownDividend"); diff --git a/lib/polyfinf.gi b/lib/polyfinf.gi index 99370cfd63..089ffb92dd 100644 --- a/lib/polyfinf.gi +++ b/lib/polyfinf.gi @@ -747,7 +747,7 @@ local v, R, U, x, O, n, g, q, o, bas; [IndeterminateNumberOfLaurentPolynomial(f)]); U := FFPUpperBoundOrder( R, f ); - # run through the irrducibles and compute their order + # run through the irreducibles and compute their order x := IndeterminateOfUnivariateRationalFunction(f); O := []; n := 1; diff --git a/lib/polyrat.gi b/lib/polyrat.gi index 91bcfad514..42f69b8217 100644 --- a/lib/polyrat.gi +++ b/lib/polyrat.gi @@ -1009,7 +1009,7 @@ local pol,n,nalpha,d,dis,rb,bound,a,i,j,k,l,w,bin,lm,bea,polc,ro,rbpow; # we want an upper bound of the root, RootInt will give a lower # bound. So we compute the root of w-1 (in case w is a perfect square) # and add 1. As we nowhere selected a specific galois representative, - # this bound (which is rational!) will bound all conjugactes as well. + # this bound (which is rational!) will bound all conjugates as well. lm:=(RootInt(Int(w)-1,2)+1); for k in [1..DegreeOfLaurentPolynomial(pol)] do diff --git a/lib/ratfun.gi b/lib/ratfun.gi index 9da8515a67..98efbdf29c 100644 --- a/lib/ratfun.gi +++ b/lib/ratfun.gi @@ -1705,7 +1705,7 @@ local fam,tw,res,m,n,mn,r,e,s,d,dr,px,x,y,onepol,stop; fi; if n>m then - # force f to be of larger degee + # force f to be of larger degree res:=(onepol)^(n*m); tw:=f; f:=g; g:=tw; tw:=m; m:=n; n:=tw; @@ -1753,7 +1753,7 @@ local fam,tw,res,m,n,mn,r,e,s,d,dr,px,x,y,onepol,stop; n:=dr; f:=g; -# was: g:=r/(x*y^mn) However the double division seems more gently; +# was: g:=r/(x*y^mn) However the double division seems gentler; g:=r/x/y^mn; x:=LeadingCoefficient(f,ind); y:=x^mn/y^(mn-1); @@ -1833,7 +1833,7 @@ end); # # 11-15-04, WDJ and AH -# n is the number of terms in m. n1 is the number of variable occurring +# n is the number of terms in m. n1 is the number of variables occurring # in each monomial term of m. returns the degrees of each variable in the # monomial m. BindGlobal("MVFactorDegreeMonomialTerm",function(m) diff --git a/lib/ratfun1.gi b/lib/ratfun1.gi index 554ae3ee13..eb8fcb2bee 100644 --- a/lib/ratfun1.gi +++ b/lib/ratfun1.gi @@ -176,7 +176,7 @@ local fam,notuniv,cannot,num,den,hasden,indn,col,dcol,val,i,j,nud,pos; fi; col:=[]; - nud:=1; # last position isto which we can assign without holes + nud:=1; # last position up to which we can assign without holes # now process the numerator for i in [2,4..Length(num)] do @@ -224,7 +224,7 @@ local fam,notuniv,cannot,num,den,hasden,indn,col,dcol,val,i,j,nud,pos; if hasden then dcol:=[]; - nud:=1; # last position isto which we can assign without holes + nud:=1; # last position up to which we can assign without holes # because we have a special hook above for laurent polynomials, we know # it cannot be a laurent polynomial any longer. @@ -321,7 +321,7 @@ local f; fi; fi; - # slightly better to do this after the Length id determined + # slightly better to do this after the Length is determined if IsFFECollection(ncof) and IS_PLIST_REP(ncof) then ConvertToVectorRep(ncof); fi; diff --git a/lib/ratfunul.gi b/lib/ratfunul.gi index a06bd9bbdb..9fa99567ed 100644 --- a/lib/ratfunul.gi +++ b/lib/ratfunul.gi @@ -603,7 +603,7 @@ end); ## #M / (if possible) ## -## While w rely for ordinary rat. fun. on a*Inverse(b) we do not want this +## While we rely for ordinary rat. fun. on a*Inverse(b) we do not want this ## for laurent polynomials, as the inverse would have to be represented as ## a rational function, not a laurent polynomial. InstallMethod(\/,"upol/upol",true, diff --git a/lib/ringhom.gi b/lib/ringhom.gi index 7205e5b85b..98e25249d1 100644 --- a/lib/ringhom.gi +++ b/lib/ringhom.gi @@ -603,7 +603,7 @@ function( R, I ) # SNF gives R*M*C=D, so $R^-1*D*C^-1*(x,y)^T=0$, implying that D are # relations that hold amongst C^-1*(x,y). Thus: # The rows of C^-1 express the new generators in terms of the old, i.e. - # are base chance new-> old as row vectors. + # are base change new-> old as row vectors. # the rows of C convert old->new # Thus the rows of C give coefficients for images of old generators diff --git a/lib/ringsc.gd b/lib/ringsc.gd index 9871317d71..01d73541c9 100644 --- a/lib/ringsc.gd +++ b/lib/ringsc.gd @@ -9,7 +9,7 @@ ## SPDX-License-Identifier: GPL-2.0-or-later ## ## This file contains declarations for elements of rings, given as Z-modules -## with structure constants for multiplication. Is is based on algsc.gd +## with structure constants for multiplication. It is based on algsc.gd ## ############################################################################# @@ -66,10 +66,10 @@ DeclareGlobalFunction( "RingByStructureConstants" ); #F StandardGeneratorsSubringSCRing( ) ## ## for a subring of an SC ring this command returns a list of length 3. -## The first entry are generators for as addive group, given with +## The first entries are generators for as additive group, given with ## respect to the additive group basis for and being in hermite normal ## form. The second entries are pivot positions for these generators. The third -## entry are the generators as actual ring elements. +## entries are the generators as actual ring elements. DeclareAttribute("StandardGeneratorsSubringSCRing",IsSubringSCRing); ############################################################################# diff --git a/lib/schur.gd b/lib/schur.gd index 866e02ff04..a8832c2841 100644 --- a/lib/schur.gd +++ b/lib/schur.gd @@ -272,7 +272,7 @@ DeclareGlobalFunction("CorestEval"); ## ## ## -## Let hom an epimorphism from an fp group onto a finite group G. This +## Let hom be an epimorphism from an fp group onto a finite group G. This ## function returns an epimorphism onto the p-Sylow subgroup of G, ## whose kernel is the largest quotient of the multiplier, that can lift ## hom to a larger quotient. (The source of this map thus is M_R(B) diff --git a/lib/schur.gi b/lib/schur.gi index b34a4608c9..1ec7393830 100644 --- a/lib/schur.gi +++ b/lib/schur.gi @@ -733,7 +733,7 @@ InstallMethod(EpimorphismNonabelianExteriorSquare, "Naive method", true, ## #P IsCentralFactor() ## -## Dertermines if $G$ is a central factor of some group $H$ or not. +## Determines if $G$ is a central factor of some group $H$ or not. ## InstallMethod(IsCentralFactor, "Naive method", true, [IsGroup], 0, G -> IsTrivial(Epicentre(G))); diff --git a/lib/straight.gd b/lib/straight.gd index 0e50089313..cea979440f 100644 --- a/lib/straight.gd +++ b/lib/straight.gd @@ -752,8 +752,8 @@ DeclareGlobalFunction( "SLPReversedRenumbered" ); ## In both cases the resulting slp ## does only what is necessary. Obviously, the slp must have a line with ## enough expressions (lists) for the supplied k as its last line. -## slp is either an slp or a pair where the first entry are the lines -## of the slp and the second is the number of inputs. +## slp is either an slp or a pair where the first entry is the list +## of lines of the slp and the second is the number of inputs. ## ## ## <#/GAPDoc> @@ -770,8 +770,8 @@ DeclareGlobalFunction( "RestrictOutputsOfSLP" ); ## ## Returns a new slp that calculates only the value of slot k ## at the end of slp doing only what is necessary. -## slp is either an slp or a pair where the first entry are the lines -## of the slp and the second is the number of inputs. +## slp is either an slp or a pair where the first entry is the list +## of lines of the slp and the second is the number of inputs. ## Note that this assumes a general SLP with possible overwriting. ## If you know that your SLP does not overwrite slots, please use ## , diff --git a/lib/system.g b/lib/system.g index bc763b0fc8..731c78b6f4 100644 --- a/lib/system.g +++ b/lib/system.g @@ -560,7 +560,7 @@ end ); ## <#/GAPDoc> ## BIND_GLOBAL("ARCH_IS_WINDOWS",function() - # Exit early is we are not in Cygwin + # Exit early if we are not in Cygwin if POSITION_SUBSTRING (GAPInfo.Architecture, "cygwin", 0) = fail then return false; fi; diff --git a/lib/teaching.g b/lib/teaching.g index f05d19daa8..7251d8cb4f 100644 --- a/lib/teaching.g +++ b/lib/teaching.g @@ -9,8 +9,8 @@ ## SPDX-License-Identifier: GPL-2.0-or-later ## ## This file contains routines that are primarily of interest in a teaching -## context. It is made part of the general system to ensure it will be -## always installed with GAP. +## context. It is made part of the general system to ensure it will always +## be installed with GAP. ## ############################################################################# @@ -291,7 +291,7 @@ end); ## ## This function creates check digit test functions such as ## for check digit schemes that use the inner -## products with a fixed vector modulo a number. The scheme creates will use +## products with a fixed vector modulo a number. The scheme created will use ## strings of l digits (including the check digits), the check consists ## of taking the standard product of the vector of digits with the fixed vector ## f modulo m; the result needs to be 0. @@ -382,7 +382,7 @@ DeclareGlobalFunction("CheckDigitTestFunction"); ## message using the scheme A=11, B=12 and so on (and ## converting lower case to upper case). ## If a list of characters is given in table, -## it is used instead for encoding). +## it is used instead for encoding. ## l:=NumbersString("Twas brillig and the slithy toves",1000000); ## [ 303311, 291012, 281922, 221917, 101124, 141030, 181510, 292219, @@ -408,7 +408,7 @@ DeclareGlobalFunction("NumbersString"); ## and returns a ## message string, using the scheme A=11, B=12 and so on. ## If a list of characters is given in table, -## it is used instead for decoding). +## it is used instead for decoding. ## StringNumbers(l,1000000); ## "TWAS BRILLIG AND THE SLITHY TOVES" @@ -436,7 +436,7 @@ DeclareGlobalFunction("StringNumbers"); ## Calling for the same object o with ## s set to ## deletes the special viewing setup. -## Since use of this features potentially slows down the whole print +## Since use of this feature potentially slows down the whole print ## process, this function should be used sparingly. ## SetNameObject(3,"three"); diff --git a/lib/teachm2.g b/lib/teachm2.g index edcebc506f..66a0e316b3 100644 --- a/lib/teachm2.g +++ b/lib/teachm2.g @@ -8,7 +8,7 @@ ## ## SPDX-License-Identifier: GPL-2.0-or-later ## -## This file contains rotines for turning teaching mode on and off. +## This file contains routines for turning teaching mode on and off. ## TEACHMODE:=fail; diff --git a/lib/teachmod.g b/lib/teachmod.g index 36a6df7b32..b11ecafeeb 100644 --- a/lib/teachmod.g +++ b/lib/teachmod.g @@ -8,7 +8,7 @@ ## ## SPDX-License-Identifier: GPL-2.0-or-later ## -## This file contains rotines that enable simplified display and turn on +## This file contains routines that enable simplified display and turn on ## some naive routines, which are primarily of interest in a teaching ## context. It is made part of the general system to ensure it will be ## always installed with GAP. diff --git a/lib/twocohom.gi b/lib/twocohom.gi index 7af0728b1e..4349242427 100644 --- a/lib/twocohom.gi +++ b/lib/twocohom.gi @@ -14,7 +14,7 @@ #F CollectedWordSQ( C, u, v ) ## ## The tail of a conjugate i^j (i>j) or a power i^p (i=j) is stored at -## posiition (i^2-i)/2+j +## position (i^2-i)/2+j ## InstallGlobalFunction( CollectedWordSQ, function( C, u, v ) local w, p, c, m, g, n, i, j, x, mx, l1, l2, l; @@ -833,7 +833,7 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, # tails. hastail:=[]; rules:=[]; - genkill:=[]; # relations that kill generators. Needed for presenation. + genkill:=[]; # relations that kill generators. Needed for presentation. for r in tzrules do if Length(r[1])>=2 then Add(rules,r); @@ -1304,7 +1304,7 @@ local hom,mats,m,i,j,mo,bas,a,l,ugens,gi,r,cy,act,k,it,p; k:=Length(module.generators); hom:=GroupHomomorphismByImagesNC(G,Group(module.generators), GeneratorsOfGroup(G),module.generators); - # we allow do go immediately to normal subgroup of index up to 4. + # we allow to go immediately to normal subgroup of index up to 4. # This reduces search space it:=DescSubgroupIterator(G:skip:=LogInt(Size(G),2)); repeat @@ -1710,7 +1710,7 @@ local r,z,ogens,n,gens,str,dim,i,j,f,rels,new,quot,g,p,collect,m,e,fp,sim, fi; it:=fail; while Size(p) i[2] ); ex2:= List( ex2, i -> i[1] ); mapped:= []; - # to be quick, we need there are no duplications among the images: + # to be quick, we need there to be no duplications among the images: if Length(ex2)=Length(Set(ex2)) and not fameq then for i in [ 2, 4 .. Length( x ) ] do p:= Position( gens1, x[ i-1 ] ); @@ -1019,7 +1019,7 @@ InstallMethod( MappedWord, ## ## returns the length of the longest common prefix of two ## assoc words. -## This is here because will be used by both +## This is here because it will be used by both ## the BasicWreathProductOrdering and the ## WreathProductOrdering BindGlobal("LengthOfLongestCommonPrefixOfTwoAssocWords", diff --git a/lib/wordrep.gi b/lib/wordrep.gi index 4aa2c4287a..c66bd1e830 100644 --- a/lib/wordrep.gi +++ b/lib/wordrep.gi @@ -12,7 +12,7 @@ ## representation. ## ## Currently, there are four representations for objects with the external -## representation as list of generators numbers and exponents (so not only +## representation as list of generator numbers and exponents (so not only ## for associative words but perhaps also for elements in a finitely ## presented group). ## @@ -24,7 +24,7 @@ ## internal data. ## ## The result of an arithmetic operation with objects of the same -## representation will be also of that representation if this is possible. +## representation will also be of that representation if this is possible. ## The result of an arithmetic operation with objects of different ## representations will be the bigger one of the two if this is possible. ## Otherwise `ObjByExtRep' will choose the smallest possible representation. @@ -106,8 +106,8 @@ BindGlobal( "InfBits_AssocWord", function( Type, list ) end ); -# code for printing words in factored form. This pattern searching clearly -# is improvable +# code for printing words in factored form. This pattern searching is clearly +# improvable BindGlobal("FindSubstringPowers",function(l,n) local new,t,i,step,lstep,z,zz,j,a,k,good,bad,lim,plim; new:=0; @@ -222,7 +222,7 @@ local a,n,t, if Length(l)>0 and n=infinity then n:=2*(Maximum(List(l,AbsInt))+1); fi; - a:=FindSubstringPowers(l,n+Length(tseed)); # tseed numbers are used already + a:=FindSubstringPowers(l,n+Length(tseed)); # tseed numbers are already used else a:=[l,[]]; fi; @@ -759,7 +759,7 @@ BindGlobal( "InfBits_Less", function( u, v ) local lu, lv, # length of u/v as a list len, # difference in length of u/v as words i, # loop variable - lexico; # flag for the lexicoghraphic ordering of u and v + lexico; # flag for the lexicographic ordering of u and v u := u![1]; lu := Length(u); v := v![1]; lv := Length(v); @@ -988,7 +988,7 @@ InstallOtherMethod( ObjByExtRep, ## does the administrative work in the construction of free semigroups, ## free monoids, and free groups. ## -## is the family of objects, is a list of generators names, +## is the family of objects, is a list of generator names, ## and is the required category for the elements, that is, ## `IsAssocWord', `IsAssocWordWithOne', or `IsAssocWordWithInverse'. ## @@ -1152,7 +1152,7 @@ InstallMethod( Position, local digits, pos, i; # Check whether `obj' is in the initial segment, and if not, - # whether `obj' matches the names in the rest of the list.. + # whether `obj' matches the names in the rest of the list. pos:= Position( list![2], obj ); if pos <> fail then return pos; From 58d546ef692a7cf47e4cbe0e94dd601afb35b624 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 20 May 2026 09:13:46 +0100 Subject: [PATCH 102/114] re-edited library files, adding NC --- lib/autsr.gi | 8 +++----- lib/grpnice.gi | 2 +- lib/mapping.gd | 2 +- lib/mapping.gi | 8 ++++++++ 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/autsr.gi b/lib/autsr.gi index 942dc30593..08a8227a03 100644 --- a/lib/autsr.gi +++ b/lib/autsr.gi @@ -392,12 +392,10 @@ BindGlobal("AGSRAutomLift",function(ocr,nat,fhom,miso) # allow deducing corresponding module aut. t:=ocr.trickrels; phom:=IdentityMapping(ocr.moduleauts); - - #s:=List(t.gens,x->PreImagesRepresentative(nat,x)); - #l:=List(t.gens,x->PreImagesRepresentative(nat,ImagesRepresentative(fhom,x))); - + #s:=List(t.gens,x->PreImagesRepresentativeNC(nat,x)); + #l:=List(t.gens,x->PreImagesRepresentativeNC(nat,ImagesRepresentative(fhom,x))); # word expression for images (to have some "hom-like" property - ws:=List(t.gens,x->PreImagesRepresentative(t.epi,ImagesRepresentative(fhom,x))); + ws:=List(t.gens,x->PreImagesRepresentativeNC(t.epi,ImagesRepresentative(fhom,x))); # evaluated in pregens l:=List(ws,x->MappedWord(x,GeneratorsOfGroup(t.free),t.pregens)); diff --git a/lib/grpnice.gi b/lib/grpnice.gi index bef0345638..4b42be2583 100644 --- a/lib/grpnice.gi +++ b/lib/grpnice.gi @@ -1007,7 +1007,7 @@ function( hom, elm ) local p; # avoid the double dispatch for `AsGroupGeneralMappingByImages' PushOptions( rec( Run_In_GGMBI:= true ) ); - p:=PreImagesRepresentative( AsGroupGeneralMappingByImages( hom ), elm ); + p:=PreImagesRepresentativeNC( AsGroupGeneralMappingByImages( hom ), elm ); PopOptions(); return p; end ); diff --git a/lib/mapping.gd b/lib/mapping.gd index a358a28708..f9cdf29811 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -977,7 +977,7 @@ DeclareGlobalFunction( "Images" ); ## ## ## If elm is an element of the range of the general mapping -## map then returns the set of all +## map then returns the set of all ## preimages of elm under map. ##

## From &GAP; version 4.16.1 diff --git a/lib/mapping.gi b/lib/mapping.gi index 86945f23e2..e0ff26ef8c 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -1323,6 +1323,14 @@ InstallMethod( PreImagesRepresentativeNC, Error( "no default method for s.p. general mapping" ); end ); +InstallMethod( PreImagesRepresentativeNC, + "for s.p. general mapping, and element", + FamRangeEqFamElm, + [ IsSPGeneralMapping, IsObject ], 0, + function( map, elm ) + Error( "no default method for s.p. general mapping" ); + end ); + ############################################################################# ## From 836425e15b45b92d0bd19feaca8804e806c4e34d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 8 Jun 2026 11:15:49 +0200 Subject: [PATCH 103/114] kernel: improve `ErrorReturnVoid` break-loop message (#6416) ... and in general make its phrasing more consistent. Also update some several outdated sections of the documentation about break loops and error handling. Co-authored-by: Codex --- doc/ref/mloop.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/ref/mloop.xml b/doc/ref/mloop.xml index 4f0ff1dda2..2f8831aaf6 100644 --- a/doc/ref/mloop.xml +++ b/doc/ref/mloop.xml @@ -478,6 +478,7 @@ indicate that you are in a break loop. 1/0; Error, Rational operations: must not be zero +Stack trace: not in any function at *stdin*:2 you can enter 'quit;' to quit to outer loop ]]> From e686be5ea2ccae30a10eb887227d58af53dd4617 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 10 Jun 2026 16:56:55 +0200 Subject: [PATCH 104/114] Further unify messages before break loop (#6434) * Align and clarify break loop instructions further * Adjust blocks to new late error msg * Regenerate tst/testspecial --- doc/tut/migrat.xml | 1227 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1227 insertions(+) create mode 100644 doc/tut/migrat.xml diff --git a/doc/tut/migrat.xml b/doc/tut/migrat.xml new file mode 100644 index 0000000000..cf182c4fc2 --- /dev/null +++ b/doc/tut/migrat.xml @@ -0,0 +1,1227 @@ + + + + + + + + +Migrating to &GAP; 4 + +This chapter is intended to give users who have experience with &GAP; 3 +some information about what has changed in &GAP; 4. +

+In particular, it informs about changed command line options +(see ), +the new global variable fail (see ), +some functions that have changed their behaviour +(see ) or their names +(see ), +and some conventions used for variable names (see ). +

+Then the new concepts of &GAP; 4 are sketched, +first that of mutability or immutability (see ), +with the explanation of related changes in functions that copy objects +(see ), +then the concepts of operations and method selection, which are compared +with the use of operations records in &GAP; 3 +(see , , +and ). +

+More local changes affect the concepts of notions of generation +(see ), +of parents (see ), +of homomorphisms (see , +, +and ), +how elements in finitely presented groups are treated +(see ), +how information about progress of computations can be obtained +(see ), +and how one gets information in a break loop +(see ). +

+While a &GAP; 3 compatibility mode is provided +(see ), +its use will disable some of the new features of &GAP; 4. +Also it certainly can only try to provide partial compatibility. +

+For a detailed explanation of the new features and concepts of &GAP; 4, +see the manual Programming in GAP. + + + +

+Changed Command Line Options + +In &GAP; 4, the -l option is used to specify the root directory +(see ) +of the &GAP; distribution, +which is the directory containing the lib and doc subdirectories. +Note that in &GAP; 3 this option was used to specify the path to the +lib directory. +

+The -h option of &GAP; 3 has been removed, +the path(s) for the documentation are deduced automatically in &GAP; 4. +

+The option -g is now used to print information only about full garbage +collections. +The new option -g -g generates information about partial +garbage collections too. + +

+ + + +
+Fail + +There is a new global variable +fail instead of false +

+ + + +in &GAP; 4. +It is intended as a return value of a function for the case that it +could not perform its task. +For example, Inverse returns fail if it is called with a singular +matrix, and Position returns fail if the second argument is not +contained in the list given as first argument. +

+&GAP; 3 handled such situations by either signalling an error, +for example if it was asked for the inverse of a singular matrix, +or by (mis)using false as return value, as in the example Position. +Note that in the first example, in &GAP; 3 it was necessary to check +the invertibility of a matrix before one could safely ask for its +inverse, which meant that roughly the same work was done twice. + + + +

+ + + +
+Changed Functionality + +Some functions that were already available in &GAP; 3 behave +differently in &GAP; 4. This section lists them. +

+ + + +The &GAP; 3 manual promised that pnt would be the first entry of the +resulting orbit. This was wrong already there in a few cases, therefore +&GAP; 4 does not promise anything about the ordering of points in an orbit. + + +

+ + + +only takes the element g and computes its multiplicative order. +Calling Order with two arguments is permitted only in the +&GAP; 3 compatibility mode, see . +(Note that it does not make sense anymore to specify a group as +first argument w.r.t. which the order of the second argument shall +be computed, see .) + + +

+ + + +If obj is not contained in the list list then fail is returned +in &GAP; 4 (see ), whereas false was returned in &GAP; 3. + + +

+ + + +In &GAP; 3, this function took either two or three arguments, +the optional argument K being a subgroup of G that stabilizes prop +in the sense that for any element g in G, +either all elements or no element in the coset g * K have the +property prop. +

+The &GAP; 4 function ElementProperty, however, +takes between two and four arguments, +and the subgroup K known from &GAP; 3 has to be entered as the fourth +argument not the third. +(The third argument in the &GAP; 4 function denotes a subgroup U +stabilizing prop in the sense that either all elements or no element +in right cosets U * g have the property prop.) +

+(This discrepancy was discovered only in March 2002, +short before the release of &GAP; 4.3.) + + +

+ + + +Objects may appear on the screen in a different way, +depending on whether they are printed by the read eval print loop +or by an explicit call of Print. +The reason is that the read eval print loop calls the operation ViewObj +and not PrintObj, whereas Print calls PrintObj for each of its +arguments. +This permits the installation of methods for printing objects in a short form +in the read eval print loop while retaining Print to display +the object completely. +See also Section . +

+(PrintObj is installed as standard method ViewObj, so it is +not really necessary to have a ViewObj method for an object.) + + +

+ + + +In &GAP; 3, PrintTo could be (mis)used to redirect the text +printed by a function (that is, not only the output of a function) +to a file by entering the function call as second argument. +This was used mainly in order to avoid many calls of AppendTo. +In &GAP; 4, this feature has disappeared. +One can use streams (see Chapter ) +instead in order to write files efficiently. + + + +

+ + + +
+Changed Variable Names + +AgGroup +ApplyFunc +Backtrace +CharTable +Denominator +DepthVector +Elements +IsBijection +IsFunc +IsMat +IsRec +IsSet +LengthWord +NOfCyc +Numerator +RandomInvertableMat +RecFields +X + +Some functions have changed their name without changing the +functionality. +A -- probably incomplete -- list follows +

+ +

+See Section  for a way to make the old names +available again. + +

+ + + +
+Naming Conventions + +The way functions are named has been unified in &GAP; 4. +This might help to memorize or even guess names of library functions. +

+If a variable name consists of several words then the first +letter of each word is capitalized. +

+If the first part of the name of a function is a verb then the function +may modify its argument(s) but does not return anything, +for example Append appends the list given as second argument to the +list given as first argument. +Otherwise the function returns an object without changing the arguments, +for example Concatenation returns the concatenation of the lists +given as arguments. +

+If the name of a function contains the word By then the return value is +thought of as built in a certain way from the parts given as arguments. +For example, GroupByGenerators returns a group built from its group +generators, and creating a group as a factor group of a given group +by a normal subgroup can be done by taking the image of +NaturalHomomorphismByNormalSubgroup +(see also ). +Other examples of By functions are GroupHomomorphismByImages and +UnivariateLaurentPolynomialByCoefficients. +

+If the name of a function contains the word Of then the return value is +thought of as information deduced from the arguments. +Usually such functions are attributes +(see  in this Tutorial and ). +Examples are GeneratorsOfGroup, which returns a list of generators for +the group entered as argument, or DiagonalOfMat. +

+For the setter and tester functions of an attribute attr +(see  in this Tutorial +and ) +the names Setattr resp. Hasattr are available. +

+If the name of a function fun1 ends with NC then there is another +function fun2 with the same name except that the NC is missing. +NC stands for no check. +When fun2 is called then it checks whether its arguments are valid, +and if so then it calls fun1. +The functions SubgroupNC and Subgroup are a typical example. +

+The idea is that the possibly time consuming check of the arguments +can be omitted if one is sure that they are unnecessary. +For example, if an algorithm produces generators of the derived subgroup +of a group then it is guaranteed that they lie in the original group; +Subgroup would check this, and SubgroupNC omits the check. +

+Needless to say, all these rules are not followed slavishly, +for example there is one operation Zero instead of two operations +ZeroOfElement and ZeroOfAdditiveGroup. + +

+ + + +
+Immutable Objects + +&GAP; 4 supports immutable objects. Such objects cannot be +changed, attempting to do so issues an error. Typically attribute +values are immutable, and also the results of those binary arithmetic +operations where both arguments are immutable, +see Section . +For example, [ 1 .. 100 ] + [ 1 .. 100 ] is a +mutable list and 2 * Immutable( [ 1 .. 100 ] ) is an immutable +list, both are equal to the (mutable) list [ 2, 4 .. 200 ]. +

+There is no way to make an immutable object mutable, one can only +get a mutable copy by ShallowCopy. The other way round, +MakeImmutable makes a (mutable or immutable) object and all its +subobjects immutable; one must be very careful to use MakeImmutable +only for those objects that are really newly created, for such objects +the advantage over Immutable is that no copy is made. +

+More about immutability can be found in Sections  in +this tutorial and . + +

+ + + +
+Copy + +StructuralCopy +ShallowCopy +The function Copy of &GAP; 3 is not supported in &GAP; 4. This +function was used to create a copy cop of its argument obj with +the properties that cop and obj had no subobjects in common and +that if two subobjects of obj were identical then also the +corresponding subobjects of cop were identical. +

+The possibility of having immutable objects (see ) can and +should be used to avoid unnecessary copying. +Namely, given an immutable object one needs to copy it only if one wants +to get a modified object, and in such a situation usually it is +sufficient to use ShallowCopy, or at least one knows how deep one must +copy in order to do the changes one has in mind. +

+For example, suppose you have a matrix group, and you want to +construct a list of matrices by modifying the group generators. This +list of generators is immutable, so you call ShallowCopy to get a +mutable list that contains the same matrices. If you only want to +exchange some of them, or to append some other matrices, this shallow +copy is already what you need. So suppose that you are interested in +a list of matrices where some rows are also changed. For that, you +call ShallowCopy for the matrices in question, and you get matrices +whose rows can be changed. If you want to change single entries in +some rows, ShallowCopy must be called to get mutable copies of these +rows. Note that in all these situations there is no danger to change, +i.e., to destroy the original generators of the matrix group. +

+If one needs the facility of the Copy function of &GAP; 3 to get a +copy with the same structure then one can use the new &GAP; 4 +function StructuralCopy. It returns a structural copy that has no +mutable subobject in common with its argument. So if +StructuralCopy is called with an immutable object then this object +itself is returned, and if StructuralCopy is called with a mutable +list of immutable objects then a shallow copy of this list is +returned. +

+Note that ShallowCopy now is an operation. So if you create your +own type of (copyable) objects then you must define what a shallow +copy of these objects is, and install an appropriate method. + +

+ + + +
+Attributes vs. Record Components + +In &GAP; 3, many complex objects were represented via records, for +example all domains. Information about these objects was stored in +components of these records. For the user, this was usually not +relevant, since there were functions for computing information about +the objects in question. For example, if one was interested in the +size of a group then one could call Size. +

+But since it was guaranteed that the size of a domain D was stored +as value of the component size, it was allowed to access D.size +if this component was bound, and a check for this was possible via +IsBound( D.size ). +

+In &GAP; 4, only the access via functions is admissible. One reason +is the following basic rule. +

+From the information that a given &GAP; 4 object is for example a +domain, one cannot conclude that this object has a certain +representation. +

+For attributes like Size, &GAP; 4 provides two related functions, +the setter and the tester of the attribute, which can be used to +set an attribute value and to check whether the value of an attribute +is already stored for an object (see also ). For example, if D is a domain in &GAP; 4 then +HasSize( D ) is true if the size of D is already stored, and +false otherwise. In the latter case, if you know that the size of +D is size then you may store it by SetSize( D, size ). +

+Besides the flexibility in the internal representation of objects, +storing information only via function calls has also the advantage +that &GAP; 4 is able to draw conclusions automatically. For example, +as soon as it is stored that a group is nilpotent, it is also stored +that it is solvable, see Chapters  and  +for the details. +

+As a consequence, you cannot put your favourite information into a +domain D by assigning it to a new component like +D.myPrivateInfo. Instead you can introduce a new attribute and +then use its setter, see . + +

+ + + +
+Different Notions of Generation + +As in &GAP; 3, a domain in &GAP; 4 is a structured set. +

+The same set can have different structures, for example a field can be +regarded as a ring or as an algebra or vector space over a subfield. +

+In &GAP; 3, however, an object representing a ring did not represent +a field, and an object representing a field did not represent a ring. +One reason for this was that the record component generators was +used to denote the appropriate generators of the domain. For a ring +R, the component R.generators was a list of ring generators, and +for a field F, F.generators was a list of field generators. +

+&GAP; 4 cleans this up, see . It supports +many different notions of generation, for example one can ask for +magma generators of a group or for generators of a field as an additive +group. A subtle but important distinction is that between generators +of an algebra and of an algebra-with-one. +

+So the attributes GeneratorsOfGroup, GeneratorsOfMagma, +GeneratorsOfRing, GeneratorsOfField, GeneratorsOfVectorSpace, +and so on, replace the access to the generators component. + +

+ + + +
+Operations Records + +Already in &GAP; 3 there were several functions that were applicable +to many different kinds of objects, for example Size could be +applied to any domain, and the binary infix multiplication * could +be used to multiply two matrices, an integer with a row vector, or a +permutation with a permutation group. This was implemented as +follows. Functions like Size and * tried to find out what +situation was described by its arguments, and then it called a more +specific function to compute the desired information. These more +specific functions, let us call them methods as they are also called +in &GAP; 4, were stored in so-called operations records of the +arguments. +

+For example, every domain in &GAP; 3 was represented as a record, and +the operations record was stored in the record component operations. +If Size was called for the domain then the method to compute the +size of the domain was found as value of the Size component of the +operations record. +

+This was fine for functions taking only one argument, and in principle +it is possible that for those functions an object stored an optimal +method in its operations record. But in the case of more arguments +this is not possible. In a multiplication of two objects in &GAP; 3, +one had to choose between the methods stored in the operations records +of the arguments, and if for example the method stored for the left +operand was called, this method had to handle all possible right +operands. +

+So operations records turned out to be not flexible enough. +In &GAP; 4, operations records are not supported +(see  for a possibility +to use your &GAP; 3 code that utilizes operations records, +at least to some extent). +A detailed description +of the new mechanism to select methods can be found in +Chapter . +

+An important point is that the new mechanism allows &GAP; to take the +relation between arguments into account. So it is possible (and +recommended) to install different methods for different relations +between the arguments. Note that such methods need not do the +extensive argument checking that was necessary in &GAP; 3, because +most of the checks are done already by the method selection mechanism. + +

+ + + +
+Operations vs. Dispatcher Functions + +&GAP; 3 functions like Size, CommutatorSubgroup, or +SylowSubgroup did mainly call an appropriate method +(see ) +after they had checked their arguments. +Such functions were +called dispatchers in &GAP; 3. In &GAP; 4, many dispatchers have +been replaced by operations, due to the fact that methods are no +longer stored in operations records (see  for the details). +

+Most dispatchers taking only one argument were treated in a special +way in &GAP; 3, they had the additional task of storing computed +values and using these values in subsequent calls. For example, the +dispatcher Size first checked whether the size of the argument was +already stored, and if so then this value was returned; otherwise a +method was called, the value returned by this method was stored in the +argument, and then returned by Size. +

+In &GAP; 4, computed values of operations that take one argument +(these operations are called attributes) are also stored, only the +mechanism to achieve this has changed, see  +and . +

+So the behaviour of Size is the same in &GAP; 3 and &GAP; 4. But +note that in &GAP; 4, it is not possible to access D.size, +see . +As described in , +&GAP; 4 does not admit bypassing the dispatcher by +calling for example D.operations.Size. This was done in &GAP; 3 +often for efficiency reasons, but the method selection mechanism of +&GAP; 4 is fast enough to make this unnecessary. +

+If you had written your own dispatchers and put your own methods into +existing operations records then this code will not work in &GAP; 4. +See  +and  +for a description of how to define operations +and to install methods. +

+Finally, some functions in &GAP; 3 were hidden in +operations records, e.g., PermGroupOps.MovedPoints. +These functions became proper operations in &GAP; 4. + +

+ + + +
+Parents and Subgroups + +In &GAP; 3 there was a strict distinction between parent groups and +subgroups. +The use of the name parent (instead of supergroup) +was chosen to indicate that the parent of an object was more than just +useful information. +In fact the main reason for the introduction of parents was to provide +a common roof for example for all groups of polycyclic words that +belonged to the same PC-presentation, or for all subgroups of a finitely +presented group (see ). +A subgroup was never a parent group, and it was possible to create +subgroups only of parent groups. +

+In &GAP; 4 this common roof is provided already by the concept of +families, see . +Thus it is no longer compulsory to use parent groups at all. +On the other hand, parents may be used in &GAP; 4 to provide +information about an object, for example the normalizer of a group in its +parent group may be stored as an attribute value. +Note that there is no restriction on the supergroup that is set to be +the parent, +it is possible to create a subgroup of +any group, this group then being the parent of the new subgroup. +This permits for example chains of subgroups with respective parents, +of arbitrary length. +

+As a consequence, the Parent command cannot be used in &GAP; 4 to +test whether the two arguments of CommutatorSubgroup fit together, +this is now a question that concerns the relation between the families +of the groups. So the 2-argument version of Parent and the now +meaningless function IsParent have been abolished. + +

+ + + +
+Homomorphisms vs. General Mappings + +In &GAP; 3 there had been a confusion between group homomorphisms and +general mappings, as GroupHomomorphismByImages created only a +general mapping that did not store whether it was a mapping. This +caused expensive, unwanted, and unnecessary tests whether the mapping +was in fact a group homomorphism. Moreover, the official +workaround to set some components of the mapping record was quite +unwieldy. +

+In &GAP; 4, GroupHomomorphismByImages checks whether the desired +mapping is indeed a group homomorphism; if so then this property is +stored in the returned mapping, otherwise fail is returned. If you +want to avoid the checks then you can use +GroupHomomorphismByImagesNC. If you want to check whether a general +mapping that respects the group operations is really a group +homomorphism, you can construct it via GroupGeneralMappingByImages +and then call IsGroupHomomorphism for it. (Note that +IsGroupHomomorphism returns true if and only if both +IsGroupGeneralMapping and IsMapping do, so one does in fact check +IsMapping in this case.) +

+There is no function IsHomomorphism in &GAP; 4, +since there are several different operations with respect to which a +mapping can be a homomorphism. + +

+ + + +
+Homomorphisms vs. Factor Structures + +If F is a factor structure of G, with kernel N, complete +information about the connection between F and G is provided by +the natural homomorphism. +

+In &GAP; 3, the official way to construct this natural homomorphism +was to create first the factor structure F, and then to call +NaturalHomomorphism with the arguments G and F. +For that, the data necessary to compute the homomorphism was stored in +F when F was constructed. +

+In &GAP; 4, factor structures are not treated in a special way, +in particular they do not store information about a homomorphism. +Instead, the more natural way is taken to construct the natural +homomorphism from G and N by NaturalHomomorphismByNormalSubgroup +if N is a normal subgroup of the group G, +or by NaturalHomomorphismByIdeal if N is an ideal in the ring G. +The factor F can then be accessed as the image of this homomorphism, +and of course G is the preimage and N is the kernel. +

+Note that &GAP; 4 does not guarantee anything about the representation +of the factor F, it may be a permutation group or a polycyclically +presented group or another kind of group. +Also note that a natural homomorphism need not be surjective. +

+A consequence of this change is that &GAP; 4 does not allow you to +construct a natural homomorphism from the groups G and F. +

+The other common type of homomorphism in &GAP; 3, operation +homomorphisms, have been replaced (just a name change) by action +homomorphisms, which are handled in a similar fashion. That is, an +action homomorphism is constructed from an acting group, an action +domain, and a function describing the operation. The permutation +group arising by the induced action is then the image of this +operation homomorphism. +

+The &GAP; 3 function Operation is still supported, under the name Action, +but from the original group and the result of Action it is not +possible to construct the action homomorphism. + +

+ + + +
+Isomorphisms vs. Isomorphic Structures + +In &GAP; 3, a different representation of a group could be obtained by +calling AgGroup to get an isomorphic polycyclically presented group, +PermGroup to get an isomorphic permutation group, and so on. +The returned objects stored an isomorphism in the record component +bijection. +

+For the same reason as in , +&GAP; 4 puts emphasis on the isomorphism, +and the isomorphic object in the desired representation can be accessed +as its image. +So you can call IsomorphismPcGroup or IsomorphismPermGroup in order +to get an isomorphism to a polycyclically presented group or a +permutation group, respectively, and then call Image to get the +isomorphic group. +

+Note that the image of an action homomorphism with trivial kernel is +also an isomorphic permutation group, but an action homomorphism need +not be surjective, since it may be easier to define it into the full +symmetric group. +

+Further note that in &GAP; 3, a usual application of isomorphisms to +polycyclically presented groups was to utilize the usually more +effective algorithms for solvable groups. However, the new concept of +polycyclic generating systems in &GAP; 4 makes it possible to apply +these algorithms to arbitrary solvable groups, independent of the +representation. For example, &GAP; 4 can handle polycyclic +generating systems of solvable permutation groups. So in many cases, +a change of the representation for efficiency reasons may be not +necessary any longer. +

+In general IsomorphismFpGroup will define a presentation on generators +chosen by the algorithm. The corresponding elements of the original +group can be obtained by the command +

+PreImagesRepresentative(isofp,i)); +]]> +

+If a presentation in the given generators is needed, the command +IsomorphismFpGroupByGenerators(G, gens) will produce one. + +

+ + + +
+Elements of Finitely Presented Groups + +Strictly speaking, &GAP; 3 did not support elements of finitely +presented groups. Instead, the words in abstract generators of +the underlying free groups were (mis)used. This caused problems +whenever calculations with elements were involved, the most obvious +ones being wrong results of element comparisons. Also functions +that should in principle work for any group were not applicable to +finitely presented groups. In effect, a finitely presented group had +to be treated in a special way in &GAP; 3. +

+&GAP; 4 distinguishes free groups and their elements from finitely +presented groups and their elements. Comparing two elements of a +finitely presented group will yield either the correct result or no +result at all. +

+Note that in &GAP; 4, the arithmetic and comparison operations for +group elements do not depend on a context provided by a group that +contains the elements. In particular, in &GAP; 4 it is not +meaningful to call Order( G, g ) for a group G and an element +g. + +

+ + + +
+Polynomials + +In &GAP; 3, polynomials were defined over a field. So a polynomial over +GF(3) was different from a polynomial over GF(9), even if the +coefficients were exactly the same. +

+&GAP; 4 defines polynomials only over a characteristic. This makes it +possible for example to multiply a polynomial over GF(3) with a polynomial +over GF(9) without the need to convert the former to the larger field. +

+However it has an effect on the result of DefaultRing for polynomials: +In &GAP; 3 the default ring for a polynomial was the polynomial ring of the +field over which the polynomial was defined. In &GAP; 4 no field is +associated, so (to avoid having to define the algebraic closure as the only +other sensible alternative) the default ring of a polynomial is the +DefaultRing of its coefficients. +

+This has an effect on Factors: If no ring is given, a polynomial is +factorized over its DefaultRing and so Factors(poly) +might return different results. +

+To be safe from this problem, if you are not working over prime fields, +rather call Factors(pring,poly) with the appropriate polynomial ring +and change your code accordingly. + +

+ + + +
+The Info Mechanism + +Sometimes it is useful to get information about the progress of a +calculation. +Many &GAP; functions contain statements to display such information +under certain conditions. +

+In &GAP; 3, these statements were calls to functions such as +InfoGroup1 or InfoGroup2, and if the user assigned Print to +these variables then this had the effect to switch on the printing of +information. +InfoGroup2 was used for more detailed information than InfoGroup1. +One could switch off the printing again by assigning Ignore to the +variables, and Ignore was also the default value. +

+&GAP; 4 uses one function Info for the same purpose, +which is a function that takes as first argument an info class such as +InfoGroup, as second argument an info level, and the print statements +as remaining arguments. +The level of an info class class is set to level by calling +SetInfoLevel( class, level ). +An Info statement is printed only if its second argument is smaller than +or equal to the current info level. +

+ test:= function( obj ) +> Info( InfoGroup, 2, "This is useful, isn't it?" ); +> return obj; +> end;; +gap> test( 1 ); +1 +gap> SetInfoLevel( InfoGroup, 2 ); +gap> test( 1 ); +#I This is useful, isn't it? +1 +]]> +

+As in &GAP; 3, if an info statement is ignored then its arguments are +not evaluated. + +

+ + + +
+Debugging + +Backtrace +DownEnv +Where +If &GAP; 4 runs into an error or is interrupted, +it enters a break loop. +The command Where( number ), which replaces Backtrace of &GAP; 3, +can be used to display number lines of information about the current +function call stack. +

+As in &GAP; 3, access is only possible to the variables of the current +level in the function stack, +but in &GAP; 4 the function DownEnv, with a positive or negative +integer as argument, permits one to step down or up in the +stack. +

+When interrupting, the first line printed by Where actually may be +one level higher, as shown below. +

+ OnBreak := function() end;; # eliminate back-tracing on entry to break loop +gap> test:= function( n ) +> if n > 3 then Error( "!\n" ); fi; test( n+1 ); end;; +gap> test( 1 ); +Error, ! +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue +brk> Where(); +Stack trace: +*[1] Error( "!\n" ); + @ *stdin*:3 + [2] test( n + 1 ); + @ *stdin*:3 + [3] test( n + 1 ); + @ *stdin*:3 + [4] test( n + 1 ); + @ *stdin*:3 +( ) + called from read-eval loop at *errin*:1 +brk> n; +4 +brk> DownEnv(); +brk> n; +3 +brk> Where(); +Stack trace: + [1] Error( "!\n" ); + @ *stdin*:3 +*[2] test( n + 1 ); + @ *stdin*:3 + [3] test( n + 1 ); + @ *stdin*:3 + [4] test( n + 1 ); + @ *stdin*:3 +( ) + called from read-eval loop at *errin*:5 +brk> DownEnv( 2 ); +brk> n; +1 +brk> Where(); +Stack trace: + [1] Error( "!\n" ); + @ *stdin*:3 + [2] test( n + 1 ); + @ *stdin*:3 + [3] test( n + 1 ); + @ *stdin*:3 +*[4] test( n + 1 ); + @ *stdin*:3 +( ) + called from read-eval loop at *errin*:8 +brk> DownEnv( -2 ); +brk> n; +3 +brk> quit; +gap> OnBreak := Where;; # restore OnBreak to its default value +]]> +

+For purposes of debugging, it can be helpful sometimes, to see what +information is stored within an object. In &GAP; 3 this was possible using +RecFields because the objects in question were represented via records. +For component objects, &GAP; 4 permits the same by +NamesOfComponents( object ), which will list all components present. + +

+ + + +
+Compatibility Mode + +For users who want to use &GAP; 3 code with as little changes as +possible, a compatibility mode is provided by &GAP; 4. +This mode must be turned on explicitly by the user. +

+It should be noted that this compatibility mode has not been tested +thoroughly. +

+The compatibility mode can be turned on by loading some of the following +files with ReadLib. +The different files address different aspects of compatibility. +

+ +compat3a.g + + makes some &GAP; 3 function names available that were changed + in &GAP; 4, + and provides code for some &GAP; 3 features that were + deliberately left out from the &GAP; 4 library. + For example, + almost all variable names concerning character theory that are + mentioned in the &GAP; 3 manual, + such as CharTable and SubgroupFusions, + are available after compat3a.g has been read; + the only exceptions are names of operations records. + +compat3b.g + + implements the availability of components of domains; + besides components that have no meaning for the rest of the &GAP; 4 + library, such as D.myInfo, there are components associated to + attributes; for example D.size is redirected to the call of the + attribute Size, IsBound( D.size ) to the call of its tester, + and D.size:= val to the call of its setter. + (An important special case is the component operations, see below.) + +compat3c.g + + permits you to implement your own elements represented as records, + and using operations records to provide a Print method and + the basic arithmetic operations. + When using operations records, it is probably a good idea to + use immutable operations records; for example, if the results + of arithmetic operations are records with operations records then + this avoids to create shallow copies of the operations records + in the call to Immutable for the results. + + +

+The following features are accessible only via starting &GAP; with +the command line option -O and may damage some features of &GAP; 4 +permanently for the current session. +

+ With this option, also the files listed above are read automatically. +

+ +compat3d.g + + provides some &GAP; 3 functions like Domain, simulates the + &GAP; 3 behaviour of IsString (to convert a list to string + representation if possible), and replaces fail by false; + these changes destroy parts of the functionality of &GAP; 4. + + +

+Some words concerning the simulation of operations records may be +necessary. +

+The operations records of the &GAP; 3 library, such as DomainOps +and GroupOps, are available only for access to their components, +whose values are &GAP; 4 operations; for example, the value of both +DomainOps.Size and GroupOps.Size is the operation Size. So it +is not safely possible to delegate from a Size method in another +operations record to DomainOps.Size. Also it is not possible to +change these predefined operations records. +

+If one wants to install individual methods for a given object obj +via the mechanism of operations records then one can construct a new +operations record with OperationsRecord, assign the desired methods +to components of this record, and then assign the operations record to +obj.operations. Whenever an operation that is associated with a +component nam of the operations record is called with obj as first +argument, the value of nam is chosen as the method. +

+In the case of the binary operations =, <, +, -, *, /, +Comm, and LeftQuotient, +this also happens if obj is the right-hand argument. +As in &GAP; 3, if both arguments of one of the above binary operations +have operations records containing a function for this operation, +then the function in the operations record of the right-hand argument +is chosen. +

+We give a small example how the compatibility mode works. +

+Suppose we want to deal with new objects that are derived from known +field elements by distorting their multiplication. Namely, let a' +and b' be the new objects corresponding to the field elements a, +b, and define a' * b' = a b - a - b + 2. +

+In &GAP; 3, this problem was solved by representing each new object +by a record that stored the corresponding old object and an +operations record, where the latter was a record containing the +functions applicable to the new object. After the library file +compat3c.g has been read, we can use this construction of the +operations record and of the new objects. Note that operations +records must be created with the function OperationsRecord (this was +also the norm in &GAP; 3), starting with an empty record would not work. +For our intended application, we thus start with the following two +lines of code. +

+ ReadLib( "compat3c.g" ); +gap> MyOps:= OperationsRecord( "MyOps" );; +HasMyOps := NewFilter( "HasMyOps" ); +]]> +

+In order to make the translation from &GAP; 3 code to &GAP; 4 +easier, &GAP; prints the definition of filters associated with +operations records and the method installations for operations +corresponding to components of the operations records. The output +line printed by &GAP; after the call of OperationsRecord is one +such case. +

+Now we add our multiplication function to the operations record, +and again &GAP; 4 prints a translation to &GAP; 4 code. +

+ MyOps.\* := function( a, b ) +> return rec( x:= a.x * b.x - a.x - b.x + 2, +> operations := MyOps ); +> end;; +# If the following method installation matches the requirements +# of the operation `PROD' then `InstallMethod' should be used. +# It might be useful to replace the rank `SUM_FLAGS' by `0'. +InstallOtherMethod( PROD, + "for object with `MyOps' as first argument", + true, + [ HasMyOps, IsObject ], SUM_FLAGS, + MyOps.\* ); + +# For binary infix operators, a second method is installed +# for the case that the object with `MyOps' is the right operand; +# since this case has higher priority in GAP 3, the method is +# installed with higher rank `SUM_FLAGS + 1'. +InstallOtherMethod( PROD, + "for object with `MyOps' as second argument", + true, + [ IsObject, HasMyOps ], SUM_FLAGS + 1, + MyOps.\* ); +]]> +

+Let us look how this installation works. +

+ a:= rec( x:= 3, operations:= MyOps ); +rec( x := 3, operations := MyOps ) +gap> b:= rec( x:= 5, operations:= MyOps ); +rec( x := 5, operations := MyOps ) +gap> a * b; +rec( x := 9, operations := MyOps ) +]]> +

+(In more complicated cases, we might run into problems, but this was +already the case in &GAP; 3. For example, suppose we want to support +the multiplication of two operands having different operations +records; then it is not clear which of the two multiplication +functions is to be chosen, and in &GAP; 3, the only way out was to +change the multiplication functions, in order to make them aware of +such situations.) +

+If we are now interested to translate the code to &GAP; 4 in the +sense that no compatibility mode is needed, we can use what &GAP; 4 +has printed above. (The same example is dealt with in +Chapter .) +

+The objects will no longer be records with operations component. +Instead of records we may use so-called component objects +with record-like access to components, +and instead of the operations component, we give the objects a +type that has the filter HasMyOps set. +

+ +

+(More about families and representations in this context can be found +in the chapter of Programming in &GAP; mentioned above.) +

+The next step is to write a function that creates a new object. +It may look as follows. +

+ +

+The multiplication function shall return an object with the +filter HasMyOp, so we change it as follows. +

+ MyMult := function( a, b ) +> return MyObject( x:= a!.x * b!.x - a!.x - b!.x + 2 ); +> end;; +]]> +

+Note that the component access for these objects +works via !. instead of .; +further note that no operations record needs to appear here, +the filter takes its role. +

+Finally, we install the multiplication for at least one argument +with the new filter, as had been printed by &GAP; 4 in the +session shown above. +

+ +

+And now it works (again). +

+ a:= MyObject( 3 ); + +gap> b:= MyObject( 5 ); + +gap> a * b; + +gap> last!.x +9 +]]> +

+We may install a method to print our objects in a nice way; +we could have done this for the operations record MyOps +in the compatibility mode, +the printed output would look similar to the following. +

+ +

+Now output looks as follows. +

+ a; b; a * b; +MyObject( 3 ) +MyObject( 5 ) +MyObject( 9 ) +]]> +

+Maybe now we want to improve the installation. +The multiplication function we want to use is apparently +thought only for the case that both operands have +the filter HasMyOps (and a component x). +So it is reasonable to replace the two methods for +the multiplication by one method for which both arguments +are required to have the filter. +

+ +

+At first sight, the &GAP; 4 approach seems to be much more +complicated. +But the last example shows that in &GAP; 4, +each method can be installed more specifically for the appropriate +situation. +Moreover, it is for example possible to install a method +for the multiplication of an integer and a HasMyOps object; +note that --contrary to the situation in &GAP; 3-- +such a method is independent from already existing methods +in the sense that these need not be changed when +new functionality is added. +

+Another example that uses this part of the compatibility mode can be +found in the file tst/compat3.tst of the &GAP; 4 distribution. + + + + + + + + From eb1b3b746375f58e1dfa6e2ab5d07aa8f41dad21 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 10 Jun 2026 23:11:13 +0200 Subject: [PATCH 105/114] Remove dev/migratedoc.tex and doc/tut/migrat.xml (#6431) They are not referenced anywhere and nowadays at most of historical interest. --- doc/tut/migrat.xml | 1227 -------------------------------------------- 1 file changed, 1227 deletions(-) delete mode 100644 doc/tut/migrat.xml diff --git a/doc/tut/migrat.xml b/doc/tut/migrat.xml deleted file mode 100644 index cf182c4fc2..0000000000 --- a/doc/tut/migrat.xml +++ /dev/null @@ -1,1227 +0,0 @@ - - - - - - - - -Migrating to &GAP; 4 - -This chapter is intended to give users who have experience with &GAP; 3 -some information about what has changed in &GAP; 4. -

-In particular, it informs about changed command line options -(see ), -the new global variable fail (see ), -some functions that have changed their behaviour -(see ) or their names -(see ), -and some conventions used for variable names (see ). -

-Then the new concepts of &GAP; 4 are sketched, -first that of mutability or immutability (see ), -with the explanation of related changes in functions that copy objects -(see ), -then the concepts of operations and method selection, which are compared -with the use of operations records in &GAP; 3 -(see , , -and ). -

-More local changes affect the concepts of notions of generation -(see ), -of parents (see ), -of homomorphisms (see , -, -and ), -how elements in finitely presented groups are treated -(see ), -how information about progress of computations can be obtained -(see ), -and how one gets information in a break loop -(see ). -

-While a &GAP; 3 compatibility mode is provided -(see ), -its use will disable some of the new features of &GAP; 4. -Also it certainly can only try to provide partial compatibility. -

-For a detailed explanation of the new features and concepts of &GAP; 4, -see the manual Programming in GAP. - - - -

-Changed Command Line Options - -In &GAP; 4, the -l option is used to specify the root directory -(see ) -of the &GAP; distribution, -which is the directory containing the lib and doc subdirectories. -Note that in &GAP; 3 this option was used to specify the path to the -lib directory. -

-The -h option of &GAP; 3 has been removed, -the path(s) for the documentation are deduced automatically in &GAP; 4. -

-The option -g is now used to print information only about full garbage -collections. -The new option -g -g generates information about partial -garbage collections too. - -

- - - -
-Fail - -There is a new global variable -fail instead of false -

- - - -in &GAP; 4. -It is intended as a return value of a function for the case that it -could not perform its task. -For example, Inverse returns fail if it is called with a singular -matrix, and Position returns fail if the second argument is not -contained in the list given as first argument. -

-&GAP; 3 handled such situations by either signalling an error, -for example if it was asked for the inverse of a singular matrix, -or by (mis)using false as return value, as in the example Position. -Note that in the first example, in &GAP; 3 it was necessary to check -the invertibility of a matrix before one could safely ask for its -inverse, which meant that roughly the same work was done twice. - - - -

- - - -
-Changed Functionality - -Some functions that were already available in &GAP; 3 behave -differently in &GAP; 4. This section lists them. -

- - - -The &GAP; 3 manual promised that pnt would be the first entry of the -resulting orbit. This was wrong already there in a few cases, therefore -&GAP; 4 does not promise anything about the ordering of points in an orbit. - - -

- - - -only takes the element g and computes its multiplicative order. -Calling Order with two arguments is permitted only in the -&GAP; 3 compatibility mode, see . -(Note that it does not make sense anymore to specify a group as -first argument w.r.t. which the order of the second argument shall -be computed, see .) - - -

- - - -If obj is not contained in the list list then fail is returned -in &GAP; 4 (see ), whereas false was returned in &GAP; 3. - - -

- - - -In &GAP; 3, this function took either two or three arguments, -the optional argument K being a subgroup of G that stabilizes prop -in the sense that for any element g in G, -either all elements or no element in the coset g * K have the -property prop. -

-The &GAP; 4 function ElementProperty, however, -takes between two and four arguments, -and the subgroup K known from &GAP; 3 has to be entered as the fourth -argument not the third. -(The third argument in the &GAP; 4 function denotes a subgroup U -stabilizing prop in the sense that either all elements or no element -in right cosets U * g have the property prop.) -

-(This discrepancy was discovered only in March 2002, -short before the release of &GAP; 4.3.) - - -

- - - -Objects may appear on the screen in a different way, -depending on whether they are printed by the read eval print loop -or by an explicit call of Print. -The reason is that the read eval print loop calls the operation ViewObj -and not PrintObj, whereas Print calls PrintObj for each of its -arguments. -This permits the installation of methods for printing objects in a short form -in the read eval print loop while retaining Print to display -the object completely. -See also Section . -

-(PrintObj is installed as standard method ViewObj, so it is -not really necessary to have a ViewObj method for an object.) - - -

- - - -In &GAP; 3, PrintTo could be (mis)used to redirect the text -printed by a function (that is, not only the output of a function) -to a file by entering the function call as second argument. -This was used mainly in order to avoid many calls of AppendTo. -In &GAP; 4, this feature has disappeared. -One can use streams (see Chapter ) -instead in order to write files efficiently. - - - -

- - - -
-Changed Variable Names - -AgGroup -ApplyFunc -Backtrace -CharTable -Denominator -DepthVector -Elements -IsBijection -IsFunc -IsMat -IsRec -IsSet -LengthWord -NOfCyc -Numerator -RandomInvertableMat -RecFields -X - -Some functions have changed their name without changing the -functionality. -A -- probably incomplete -- list follows -

- -

-See Section  for a way to make the old names -available again. - -

- - - -
-Naming Conventions - -The way functions are named has been unified in &GAP; 4. -This might help to memorize or even guess names of library functions. -

-If a variable name consists of several words then the first -letter of each word is capitalized. -

-If the first part of the name of a function is a verb then the function -may modify its argument(s) but does not return anything, -for example Append appends the list given as second argument to the -list given as first argument. -Otherwise the function returns an object without changing the arguments, -for example Concatenation returns the concatenation of the lists -given as arguments. -

-If the name of a function contains the word By then the return value is -thought of as built in a certain way from the parts given as arguments. -For example, GroupByGenerators returns a group built from its group -generators, and creating a group as a factor group of a given group -by a normal subgroup can be done by taking the image of -NaturalHomomorphismByNormalSubgroup -(see also ). -Other examples of By functions are GroupHomomorphismByImages and -UnivariateLaurentPolynomialByCoefficients. -

-If the name of a function contains the word Of then the return value is -thought of as information deduced from the arguments. -Usually such functions are attributes -(see  in this Tutorial and ). -Examples are GeneratorsOfGroup, which returns a list of generators for -the group entered as argument, or DiagonalOfMat. -

-For the setter and tester functions of an attribute attr -(see  in this Tutorial -and ) -the names Setattr resp. Hasattr are available. -

-If the name of a function fun1 ends with NC then there is another -function fun2 with the same name except that the NC is missing. -NC stands for no check. -When fun2 is called then it checks whether its arguments are valid, -and if so then it calls fun1. -The functions SubgroupNC and Subgroup are a typical example. -

-The idea is that the possibly time consuming check of the arguments -can be omitted if one is sure that they are unnecessary. -For example, if an algorithm produces generators of the derived subgroup -of a group then it is guaranteed that they lie in the original group; -Subgroup would check this, and SubgroupNC omits the check. -

-Needless to say, all these rules are not followed slavishly, -for example there is one operation Zero instead of two operations -ZeroOfElement and ZeroOfAdditiveGroup. - -

- - - -
-Immutable Objects - -&GAP; 4 supports immutable objects. Such objects cannot be -changed, attempting to do so issues an error. Typically attribute -values are immutable, and also the results of those binary arithmetic -operations where both arguments are immutable, -see Section . -For example, [ 1 .. 100 ] + [ 1 .. 100 ] is a -mutable list and 2 * Immutable( [ 1 .. 100 ] ) is an immutable -list, both are equal to the (mutable) list [ 2, 4 .. 200 ]. -

-There is no way to make an immutable object mutable, one can only -get a mutable copy by ShallowCopy. The other way round, -MakeImmutable makes a (mutable or immutable) object and all its -subobjects immutable; one must be very careful to use MakeImmutable -only for those objects that are really newly created, for such objects -the advantage over Immutable is that no copy is made. -

-More about immutability can be found in Sections  in -this tutorial and . - -

- - - -
-Copy - -StructuralCopy -ShallowCopy -The function Copy of &GAP; 3 is not supported in &GAP; 4. This -function was used to create a copy cop of its argument obj with -the properties that cop and obj had no subobjects in common and -that if two subobjects of obj were identical then also the -corresponding subobjects of cop were identical. -

-The possibility of having immutable objects (see ) can and -should be used to avoid unnecessary copying. -Namely, given an immutable object one needs to copy it only if one wants -to get a modified object, and in such a situation usually it is -sufficient to use ShallowCopy, or at least one knows how deep one must -copy in order to do the changes one has in mind. -

-For example, suppose you have a matrix group, and you want to -construct a list of matrices by modifying the group generators. This -list of generators is immutable, so you call ShallowCopy to get a -mutable list that contains the same matrices. If you only want to -exchange some of them, or to append some other matrices, this shallow -copy is already what you need. So suppose that you are interested in -a list of matrices where some rows are also changed. For that, you -call ShallowCopy for the matrices in question, and you get matrices -whose rows can be changed. If you want to change single entries in -some rows, ShallowCopy must be called to get mutable copies of these -rows. Note that in all these situations there is no danger to change, -i.e., to destroy the original generators of the matrix group. -

-If one needs the facility of the Copy function of &GAP; 3 to get a -copy with the same structure then one can use the new &GAP; 4 -function StructuralCopy. It returns a structural copy that has no -mutable subobject in common with its argument. So if -StructuralCopy is called with an immutable object then this object -itself is returned, and if StructuralCopy is called with a mutable -list of immutable objects then a shallow copy of this list is -returned. -

-Note that ShallowCopy now is an operation. So if you create your -own type of (copyable) objects then you must define what a shallow -copy of these objects is, and install an appropriate method. - -

- - - -
-Attributes vs. Record Components - -In &GAP; 3, many complex objects were represented via records, for -example all domains. Information about these objects was stored in -components of these records. For the user, this was usually not -relevant, since there were functions for computing information about -the objects in question. For example, if one was interested in the -size of a group then one could call Size. -

-But since it was guaranteed that the size of a domain D was stored -as value of the component size, it was allowed to access D.size -if this component was bound, and a check for this was possible via -IsBound( D.size ). -

-In &GAP; 4, only the access via functions is admissible. One reason -is the following basic rule. -

-From the information that a given &GAP; 4 object is for example a -domain, one cannot conclude that this object has a certain -representation. -

-For attributes like Size, &GAP; 4 provides two related functions, -the setter and the tester of the attribute, which can be used to -set an attribute value and to check whether the value of an attribute -is already stored for an object (see also ). For example, if D is a domain in &GAP; 4 then -HasSize( D ) is true if the size of D is already stored, and -false otherwise. In the latter case, if you know that the size of -D is size then you may store it by SetSize( D, size ). -

-Besides the flexibility in the internal representation of objects, -storing information only via function calls has also the advantage -that &GAP; 4 is able to draw conclusions automatically. For example, -as soon as it is stored that a group is nilpotent, it is also stored -that it is solvable, see Chapters  and  -for the details. -

-As a consequence, you cannot put your favourite information into a -domain D by assigning it to a new component like -D.myPrivateInfo. Instead you can introduce a new attribute and -then use its setter, see . - -

- - - -
-Different Notions of Generation - -As in &GAP; 3, a domain in &GAP; 4 is a structured set. -

-The same set can have different structures, for example a field can be -regarded as a ring or as an algebra or vector space over a subfield. -

-In &GAP; 3, however, an object representing a ring did not represent -a field, and an object representing a field did not represent a ring. -One reason for this was that the record component generators was -used to denote the appropriate generators of the domain. For a ring -R, the component R.generators was a list of ring generators, and -for a field F, F.generators was a list of field generators. -

-&GAP; 4 cleans this up, see . It supports -many different notions of generation, for example one can ask for -magma generators of a group or for generators of a field as an additive -group. A subtle but important distinction is that between generators -of an algebra and of an algebra-with-one. -

-So the attributes GeneratorsOfGroup, GeneratorsOfMagma, -GeneratorsOfRing, GeneratorsOfField, GeneratorsOfVectorSpace, -and so on, replace the access to the generators component. - -

- - - -
-Operations Records - -Already in &GAP; 3 there were several functions that were applicable -to many different kinds of objects, for example Size could be -applied to any domain, and the binary infix multiplication * could -be used to multiply two matrices, an integer with a row vector, or a -permutation with a permutation group. This was implemented as -follows. Functions like Size and * tried to find out what -situation was described by its arguments, and then it called a more -specific function to compute the desired information. These more -specific functions, let us call them methods as they are also called -in &GAP; 4, were stored in so-called operations records of the -arguments. -

-For example, every domain in &GAP; 3 was represented as a record, and -the operations record was stored in the record component operations. -If Size was called for the domain then the method to compute the -size of the domain was found as value of the Size component of the -operations record. -

-This was fine for functions taking only one argument, and in principle -it is possible that for those functions an object stored an optimal -method in its operations record. But in the case of more arguments -this is not possible. In a multiplication of two objects in &GAP; 3, -one had to choose between the methods stored in the operations records -of the arguments, and if for example the method stored for the left -operand was called, this method had to handle all possible right -operands. -

-So operations records turned out to be not flexible enough. -In &GAP; 4, operations records are not supported -(see  for a possibility -to use your &GAP; 3 code that utilizes operations records, -at least to some extent). -A detailed description -of the new mechanism to select methods can be found in -Chapter . -

-An important point is that the new mechanism allows &GAP; to take the -relation between arguments into account. So it is possible (and -recommended) to install different methods for different relations -between the arguments. Note that such methods need not do the -extensive argument checking that was necessary in &GAP; 3, because -most of the checks are done already by the method selection mechanism. - -

- - - -
-Operations vs. Dispatcher Functions - -&GAP; 3 functions like Size, CommutatorSubgroup, or -SylowSubgroup did mainly call an appropriate method -(see ) -after they had checked their arguments. -Such functions were -called dispatchers in &GAP; 3. In &GAP; 4, many dispatchers have -been replaced by operations, due to the fact that methods are no -longer stored in operations records (see  for the details). -

-Most dispatchers taking only one argument were treated in a special -way in &GAP; 3, they had the additional task of storing computed -values and using these values in subsequent calls. For example, the -dispatcher Size first checked whether the size of the argument was -already stored, and if so then this value was returned; otherwise a -method was called, the value returned by this method was stored in the -argument, and then returned by Size. -

-In &GAP; 4, computed values of operations that take one argument -(these operations are called attributes) are also stored, only the -mechanism to achieve this has changed, see  -and . -

-So the behaviour of Size is the same in &GAP; 3 and &GAP; 4. But -note that in &GAP; 4, it is not possible to access D.size, -see . -As described in , -&GAP; 4 does not admit bypassing the dispatcher by -calling for example D.operations.Size. This was done in &GAP; 3 -often for efficiency reasons, but the method selection mechanism of -&GAP; 4 is fast enough to make this unnecessary. -

-If you had written your own dispatchers and put your own methods into -existing operations records then this code will not work in &GAP; 4. -See  -and  -for a description of how to define operations -and to install methods. -

-Finally, some functions in &GAP; 3 were hidden in -operations records, e.g., PermGroupOps.MovedPoints. -These functions became proper operations in &GAP; 4. - -

- - - -
-Parents and Subgroups - -In &GAP; 3 there was a strict distinction between parent groups and -subgroups. -The use of the name parent (instead of supergroup) -was chosen to indicate that the parent of an object was more than just -useful information. -In fact the main reason for the introduction of parents was to provide -a common roof for example for all groups of polycyclic words that -belonged to the same PC-presentation, or for all subgroups of a finitely -presented group (see ). -A subgroup was never a parent group, and it was possible to create -subgroups only of parent groups. -

-In &GAP; 4 this common roof is provided already by the concept of -families, see . -Thus it is no longer compulsory to use parent groups at all. -On the other hand, parents may be used in &GAP; 4 to provide -information about an object, for example the normalizer of a group in its -parent group may be stored as an attribute value. -Note that there is no restriction on the supergroup that is set to be -the parent, -it is possible to create a subgroup of -any group, this group then being the parent of the new subgroup. -This permits for example chains of subgroups with respective parents, -of arbitrary length. -

-As a consequence, the Parent command cannot be used in &GAP; 4 to -test whether the two arguments of CommutatorSubgroup fit together, -this is now a question that concerns the relation between the families -of the groups. So the 2-argument version of Parent and the now -meaningless function IsParent have been abolished. - -

- - - -
-Homomorphisms vs. General Mappings - -In &GAP; 3 there had been a confusion between group homomorphisms and -general mappings, as GroupHomomorphismByImages created only a -general mapping that did not store whether it was a mapping. This -caused expensive, unwanted, and unnecessary tests whether the mapping -was in fact a group homomorphism. Moreover, the official -workaround to set some components of the mapping record was quite -unwieldy. -

-In &GAP; 4, GroupHomomorphismByImages checks whether the desired -mapping is indeed a group homomorphism; if so then this property is -stored in the returned mapping, otherwise fail is returned. If you -want to avoid the checks then you can use -GroupHomomorphismByImagesNC. If you want to check whether a general -mapping that respects the group operations is really a group -homomorphism, you can construct it via GroupGeneralMappingByImages -and then call IsGroupHomomorphism for it. (Note that -IsGroupHomomorphism returns true if and only if both -IsGroupGeneralMapping and IsMapping do, so one does in fact check -IsMapping in this case.) -

-There is no function IsHomomorphism in &GAP; 4, -since there are several different operations with respect to which a -mapping can be a homomorphism. - -

- - - -
-Homomorphisms vs. Factor Structures - -If F is a factor structure of G, with kernel N, complete -information about the connection between F and G is provided by -the natural homomorphism. -

-In &GAP; 3, the official way to construct this natural homomorphism -was to create first the factor structure F, and then to call -NaturalHomomorphism with the arguments G and F. -For that, the data necessary to compute the homomorphism was stored in -F when F was constructed. -

-In &GAP; 4, factor structures are not treated in a special way, -in particular they do not store information about a homomorphism. -Instead, the more natural way is taken to construct the natural -homomorphism from G and N by NaturalHomomorphismByNormalSubgroup -if N is a normal subgroup of the group G, -or by NaturalHomomorphismByIdeal if N is an ideal in the ring G. -The factor F can then be accessed as the image of this homomorphism, -and of course G is the preimage and N is the kernel. -

-Note that &GAP; 4 does not guarantee anything about the representation -of the factor F, it may be a permutation group or a polycyclically -presented group or another kind of group. -Also note that a natural homomorphism need not be surjective. -

-A consequence of this change is that &GAP; 4 does not allow you to -construct a natural homomorphism from the groups G and F. -

-The other common type of homomorphism in &GAP; 3, operation -homomorphisms, have been replaced (just a name change) by action -homomorphisms, which are handled in a similar fashion. That is, an -action homomorphism is constructed from an acting group, an action -domain, and a function describing the operation. The permutation -group arising by the induced action is then the image of this -operation homomorphism. -

-The &GAP; 3 function Operation is still supported, under the name Action, -but from the original group and the result of Action it is not -possible to construct the action homomorphism. - -

- - - -
-Isomorphisms vs. Isomorphic Structures - -In &GAP; 3, a different representation of a group could be obtained by -calling AgGroup to get an isomorphic polycyclically presented group, -PermGroup to get an isomorphic permutation group, and so on. -The returned objects stored an isomorphism in the record component -bijection. -

-For the same reason as in , -&GAP; 4 puts emphasis on the isomorphism, -and the isomorphic object in the desired representation can be accessed -as its image. -So you can call IsomorphismPcGroup or IsomorphismPermGroup in order -to get an isomorphism to a polycyclically presented group or a -permutation group, respectively, and then call Image to get the -isomorphic group. -

-Note that the image of an action homomorphism with trivial kernel is -also an isomorphic permutation group, but an action homomorphism need -not be surjective, since it may be easier to define it into the full -symmetric group. -

-Further note that in &GAP; 3, a usual application of isomorphisms to -polycyclically presented groups was to utilize the usually more -effective algorithms for solvable groups. However, the new concept of -polycyclic generating systems in &GAP; 4 makes it possible to apply -these algorithms to arbitrary solvable groups, independent of the -representation. For example, &GAP; 4 can handle polycyclic -generating systems of solvable permutation groups. So in many cases, -a change of the representation for efficiency reasons may be not -necessary any longer. -

-In general IsomorphismFpGroup will define a presentation on generators -chosen by the algorithm. The corresponding elements of the original -group can be obtained by the command -

-PreImagesRepresentative(isofp,i)); -]]> -

-If a presentation in the given generators is needed, the command -IsomorphismFpGroupByGenerators(G, gens) will produce one. - -

- - - -
-Elements of Finitely Presented Groups - -Strictly speaking, &GAP; 3 did not support elements of finitely -presented groups. Instead, the words in abstract generators of -the underlying free groups were (mis)used. This caused problems -whenever calculations with elements were involved, the most obvious -ones being wrong results of element comparisons. Also functions -that should in principle work for any group were not applicable to -finitely presented groups. In effect, a finitely presented group had -to be treated in a special way in &GAP; 3. -

-&GAP; 4 distinguishes free groups and their elements from finitely -presented groups and their elements. Comparing two elements of a -finitely presented group will yield either the correct result or no -result at all. -

-Note that in &GAP; 4, the arithmetic and comparison operations for -group elements do not depend on a context provided by a group that -contains the elements. In particular, in &GAP; 4 it is not -meaningful to call Order( G, g ) for a group G and an element -g. - -

- - - -
-Polynomials - -In &GAP; 3, polynomials were defined over a field. So a polynomial over -GF(3) was different from a polynomial over GF(9), even if the -coefficients were exactly the same. -

-&GAP; 4 defines polynomials only over a characteristic. This makes it -possible for example to multiply a polynomial over GF(3) with a polynomial -over GF(9) without the need to convert the former to the larger field. -

-However it has an effect on the result of DefaultRing for polynomials: -In &GAP; 3 the default ring for a polynomial was the polynomial ring of the -field over which the polynomial was defined. In &GAP; 4 no field is -associated, so (to avoid having to define the algebraic closure as the only -other sensible alternative) the default ring of a polynomial is the -DefaultRing of its coefficients. -

-This has an effect on Factors: If no ring is given, a polynomial is -factorized over its DefaultRing and so Factors(poly) -might return different results. -

-To be safe from this problem, if you are not working over prime fields, -rather call Factors(pring,poly) with the appropriate polynomial ring -and change your code accordingly. - -

- - - -
-The Info Mechanism - -Sometimes it is useful to get information about the progress of a -calculation. -Many &GAP; functions contain statements to display such information -under certain conditions. -

-In &GAP; 3, these statements were calls to functions such as -InfoGroup1 or InfoGroup2, and if the user assigned Print to -these variables then this had the effect to switch on the printing of -information. -InfoGroup2 was used for more detailed information than InfoGroup1. -One could switch off the printing again by assigning Ignore to the -variables, and Ignore was also the default value. -

-&GAP; 4 uses one function Info for the same purpose, -which is a function that takes as first argument an info class such as -InfoGroup, as second argument an info level, and the print statements -as remaining arguments. -The level of an info class class is set to level by calling -SetInfoLevel( class, level ). -An Info statement is printed only if its second argument is smaller than -or equal to the current info level. -

- test:= function( obj ) -> Info( InfoGroup, 2, "This is useful, isn't it?" ); -> return obj; -> end;; -gap> test( 1 ); -1 -gap> SetInfoLevel( InfoGroup, 2 ); -gap> test( 1 ); -#I This is useful, isn't it? -1 -]]> -

-As in &GAP; 3, if an info statement is ignored then its arguments are -not evaluated. - -

- - - -
-Debugging - -Backtrace -DownEnv -Where -If &GAP; 4 runs into an error or is interrupted, -it enters a break loop. -The command Where( number ), which replaces Backtrace of &GAP; 3, -can be used to display number lines of information about the current -function call stack. -

-As in &GAP; 3, access is only possible to the variables of the current -level in the function stack, -but in &GAP; 4 the function DownEnv, with a positive or negative -integer as argument, permits one to step down or up in the -stack. -

-When interrupting, the first line printed by Where actually may be -one level higher, as shown below. -

- OnBreak := function() end;; # eliminate back-tracing on entry to break loop -gap> test:= function( n ) -> if n > 3 then Error( "!\n" ); fi; test( n+1 ); end;; -gap> test( 1 ); -Error, ! -you can enter 'quit;' to quit to outer loop, or -you can enter 'return;' to continue -brk> Where(); -Stack trace: -*[1] Error( "!\n" ); - @ *stdin*:3 - [2] test( n + 1 ); - @ *stdin*:3 - [3] test( n + 1 ); - @ *stdin*:3 - [4] test( n + 1 ); - @ *stdin*:3 -( ) - called from read-eval loop at *errin*:1 -brk> n; -4 -brk> DownEnv(); -brk> n; -3 -brk> Where(); -Stack trace: - [1] Error( "!\n" ); - @ *stdin*:3 -*[2] test( n + 1 ); - @ *stdin*:3 - [3] test( n + 1 ); - @ *stdin*:3 - [4] test( n + 1 ); - @ *stdin*:3 -( ) - called from read-eval loop at *errin*:5 -brk> DownEnv( 2 ); -brk> n; -1 -brk> Where(); -Stack trace: - [1] Error( "!\n" ); - @ *stdin*:3 - [2] test( n + 1 ); - @ *stdin*:3 - [3] test( n + 1 ); - @ *stdin*:3 -*[4] test( n + 1 ); - @ *stdin*:3 -( ) - called from read-eval loop at *errin*:8 -brk> DownEnv( -2 ); -brk> n; -3 -brk> quit; -gap> OnBreak := Where;; # restore OnBreak to its default value -]]> -

-For purposes of debugging, it can be helpful sometimes, to see what -information is stored within an object. In &GAP; 3 this was possible using -RecFields because the objects in question were represented via records. -For component objects, &GAP; 4 permits the same by -NamesOfComponents( object ), which will list all components present. - -

- - - -
-Compatibility Mode - -For users who want to use &GAP; 3 code with as little changes as -possible, a compatibility mode is provided by &GAP; 4. -This mode must be turned on explicitly by the user. -

-It should be noted that this compatibility mode has not been tested -thoroughly. -

-The compatibility mode can be turned on by loading some of the following -files with ReadLib. -The different files address different aspects of compatibility. -

- -compat3a.g - - makes some &GAP; 3 function names available that were changed - in &GAP; 4, - and provides code for some &GAP; 3 features that were - deliberately left out from the &GAP; 4 library. - For example, - almost all variable names concerning character theory that are - mentioned in the &GAP; 3 manual, - such as CharTable and SubgroupFusions, - are available after compat3a.g has been read; - the only exceptions are names of operations records. - -compat3b.g - - implements the availability of components of domains; - besides components that have no meaning for the rest of the &GAP; 4 - library, such as D.myInfo, there are components associated to - attributes; for example D.size is redirected to the call of the - attribute Size, IsBound( D.size ) to the call of its tester, - and D.size:= val to the call of its setter. - (An important special case is the component operations, see below.) - -compat3c.g - - permits you to implement your own elements represented as records, - and using operations records to provide a Print method and - the basic arithmetic operations. - When using operations records, it is probably a good idea to - use immutable operations records; for example, if the results - of arithmetic operations are records with operations records then - this avoids to create shallow copies of the operations records - in the call to Immutable for the results. - - -

-The following features are accessible only via starting &GAP; with -the command line option -O and may damage some features of &GAP; 4 -permanently for the current session. -

- With this option, also the files listed above are read automatically. -

- -compat3d.g - - provides some &GAP; 3 functions like Domain, simulates the - &GAP; 3 behaviour of IsString (to convert a list to string - representation if possible), and replaces fail by false; - these changes destroy parts of the functionality of &GAP; 4. - - -

-Some words concerning the simulation of operations records may be -necessary. -

-The operations records of the &GAP; 3 library, such as DomainOps -and GroupOps, are available only for access to their components, -whose values are &GAP; 4 operations; for example, the value of both -DomainOps.Size and GroupOps.Size is the operation Size. So it -is not safely possible to delegate from a Size method in another -operations record to DomainOps.Size. Also it is not possible to -change these predefined operations records. -

-If one wants to install individual methods for a given object obj -via the mechanism of operations records then one can construct a new -operations record with OperationsRecord, assign the desired methods -to components of this record, and then assign the operations record to -obj.operations. Whenever an operation that is associated with a -component nam of the operations record is called with obj as first -argument, the value of nam is chosen as the method. -

-In the case of the binary operations =, <, +, -, *, /, -Comm, and LeftQuotient, -this also happens if obj is the right-hand argument. -As in &GAP; 3, if both arguments of one of the above binary operations -have operations records containing a function for this operation, -then the function in the operations record of the right-hand argument -is chosen. -

-We give a small example how the compatibility mode works. -

-Suppose we want to deal with new objects that are derived from known -field elements by distorting their multiplication. Namely, let a' -and b' be the new objects corresponding to the field elements a, -b, and define a' * b' = a b - a - b + 2. -

-In &GAP; 3, this problem was solved by representing each new object -by a record that stored the corresponding old object and an -operations record, where the latter was a record containing the -functions applicable to the new object. After the library file -compat3c.g has been read, we can use this construction of the -operations record and of the new objects. Note that operations -records must be created with the function OperationsRecord (this was -also the norm in &GAP; 3), starting with an empty record would not work. -For our intended application, we thus start with the following two -lines of code. -

- ReadLib( "compat3c.g" ); -gap> MyOps:= OperationsRecord( "MyOps" );; -HasMyOps := NewFilter( "HasMyOps" ); -]]> -

-In order to make the translation from &GAP; 3 code to &GAP; 4 -easier, &GAP; prints the definition of filters associated with -operations records and the method installations for operations -corresponding to components of the operations records. The output -line printed by &GAP; after the call of OperationsRecord is one -such case. -

-Now we add our multiplication function to the operations record, -and again &GAP; 4 prints a translation to &GAP; 4 code. -

- MyOps.\* := function( a, b ) -> return rec( x:= a.x * b.x - a.x - b.x + 2, -> operations := MyOps ); -> end;; -# If the following method installation matches the requirements -# of the operation `PROD' then `InstallMethod' should be used. -# It might be useful to replace the rank `SUM_FLAGS' by `0'. -InstallOtherMethod( PROD, - "for object with `MyOps' as first argument", - true, - [ HasMyOps, IsObject ], SUM_FLAGS, - MyOps.\* ); - -# For binary infix operators, a second method is installed -# for the case that the object with `MyOps' is the right operand; -# since this case has higher priority in GAP 3, the method is -# installed with higher rank `SUM_FLAGS + 1'. -InstallOtherMethod( PROD, - "for object with `MyOps' as second argument", - true, - [ IsObject, HasMyOps ], SUM_FLAGS + 1, - MyOps.\* ); -]]> -

-Let us look how this installation works. -

- a:= rec( x:= 3, operations:= MyOps ); -rec( x := 3, operations := MyOps ) -gap> b:= rec( x:= 5, operations:= MyOps ); -rec( x := 5, operations := MyOps ) -gap> a * b; -rec( x := 9, operations := MyOps ) -]]> -

-(In more complicated cases, we might run into problems, but this was -already the case in &GAP; 3. For example, suppose we want to support -the multiplication of two operands having different operations -records; then it is not clear which of the two multiplication -functions is to be chosen, and in &GAP; 3, the only way out was to -change the multiplication functions, in order to make them aware of -such situations.) -

-If we are now interested to translate the code to &GAP; 4 in the -sense that no compatibility mode is needed, we can use what &GAP; 4 -has printed above. (The same example is dealt with in -Chapter .) -

-The objects will no longer be records with operations component. -Instead of records we may use so-called component objects -with record-like access to components, -and instead of the operations component, we give the objects a -type that has the filter HasMyOps set. -

- -

-(More about families and representations in this context can be found -in the chapter of Programming in &GAP; mentioned above.) -

-The next step is to write a function that creates a new object. -It may look as follows. -

- -

-The multiplication function shall return an object with the -filter HasMyOp, so we change it as follows. -

- MyMult := function( a, b ) -> return MyObject( x:= a!.x * b!.x - a!.x - b!.x + 2 ); -> end;; -]]> -

-Note that the component access for these objects -works via !. instead of .; -further note that no operations record needs to appear here, -the filter takes its role. -

-Finally, we install the multiplication for at least one argument -with the new filter, as had been printed by &GAP; 4 in the -session shown above. -

- -

-And now it works (again). -

- a:= MyObject( 3 ); - -gap> b:= MyObject( 5 ); - -gap> a * b; - -gap> last!.x -9 -]]> -

-We may install a method to print our objects in a nice way; -we could have done this for the operations record MyOps -in the compatibility mode, -the printed output would look similar to the following. -

- -

-Now output looks as follows. -

- a; b; a * b; -MyObject( 3 ) -MyObject( 5 ) -MyObject( 9 ) -]]> -

-Maybe now we want to improve the installation. -The multiplication function we want to use is apparently -thought only for the case that both operands have -the filter HasMyOps (and a component x). -So it is reasonable to replace the two methods for -the multiplication by one method for which both arguments -are required to have the filter. -

- -

-At first sight, the &GAP; 4 approach seems to be much more -complicated. -But the last example shows that in &GAP; 4, -each method can be installed more specifically for the appropriate -situation. -Moreover, it is for example possible to install a method -for the multiplication of an integer and a HasMyOps object; -note that --contrary to the situation in &GAP; 3-- -such a method is independent from already existing methods -in the sense that these need not be changed when -new functionality is added. -

-Another example that uses this part of the compatibility mode can be -found in the file tst/compat3.tst of the &GAP; 4 distribution. - - - - - - - - From bfcd6a244a99a6674429f24a7267d0c8ef2c991c Mon Sep 17 00:00:00 2001 From: Thomas Breuer Date: Wed, 1 Jul 2026 15:18:55 +0200 Subject: [PATCH 106/114] turn the global variable `RUN_IN_GGMBI` into a global option `Run_In_GGMBI` (#6442) --- tst/testinstall/ggmbi.tst | 1 + 1 file changed, 1 insertion(+) diff --git a/tst/testinstall/ggmbi.tst b/tst/testinstall/ggmbi.tst index 801fcf79b8..de5fc68777 100644 --- a/tst/testinstall/ggmbi.tst +++ b/tst/testinstall/ggmbi.tst @@ -18,6 +18,7 @@ true gap> GroupGeneralMappingByImagesNC( G, G, gens, gens );; #I use the global option 'Run_In_GGMBI' not the global variable 'RUN_IN_GGMBI', see '?Run_In_GGMBI' gap> RUN_IN_GGMBI:= fail;; +`Run_In_GGMBI` (#6442)) # - Run some examples where the option gets set, # and where no other tests were available. From f49112051d13abd5509220b1c13417da73fe4cd6 Mon Sep 17 00:00:00 2001 From: Christopher Jefferson Date: Fri, 24 Jul 2026 00:30:54 +0100 Subject: [PATCH 107/114] New emscripten polish (#6439) Restyle the browser GAP page to match www.gap-system.org (Ubuntu fonts, GAP logo, crimson accents, dark-mode support) and vendor all runtime assets (xterm 4.17.0, xterm-pty 0.9.4, the fit addon, logo, fonts) so the deployed site has no CDN dependency. Co-authored-by: Claude Fable 5 --- etc/emscripten/README.md | 89 +++- etc/emscripten/assemble-website.sh | 23 +- etc/emscripten/build.sh | 73 ++- etc/emscripten/register_static_module.py | 36 ++ etc/emscripten/serve.py | 3 + .../web-template/coi-serviceworker.js | 79 +++- etc/emscripten/web-template/gap-fs.js | 49 +- etc/emscripten/web-template/gap-ui.js | 429 +++++++++++++++++ etc/emscripten/web-template/gap-worker.js | 219 ++++++++- etc/emscripten/web-template/index.html | 446 +++++++++++++----- etc/emscripten/web-template/vendor/README.md | 28 ++ .../web-template/vendor/favicon.svg | 79 ++++ .../web-template/vendor/fonts/UFL.txt | 96 ++++ .../vendor/fonts/Ubuntu-Bold.woff2 | Bin 0 -> 100364 bytes .../vendor/fonts/Ubuntu-Italic.woff2 | Bin 0 -> 123324 bytes .../vendor/fonts/Ubuntu-Regular.woff2 | Bin 0 -> 114668 bytes .../vendor/fonts/UbuntuMono-Bold.woff2 | Bin 0 -> 78856 bytes .../vendor/fonts/UbuntuMono-Regular.woff2 | Bin 0 -> 81412 bytes .../web-template/vendor/gaplogo.svg | 153 ++++++ .../vendor/xterm-addon-fit.min.js | 8 + .../web-template/vendor/xterm-pty/index.js | 2 + .../vendor/xterm-pty/workerTools.js | 2 + etc/emscripten/web-template/vendor/xterm.css | 175 +++++++ .../web-template/vendor/xterm.min.js | 8 + 24 files changed, 1823 insertions(+), 174 deletions(-) create mode 100644 etc/emscripten/register_static_module.py create mode 100644 etc/emscripten/web-template/gap-ui.js create mode 100644 etc/emscripten/web-template/vendor/README.md create mode 100644 etc/emscripten/web-template/vendor/favicon.svg create mode 100644 etc/emscripten/web-template/vendor/fonts/UFL.txt create mode 100644 etc/emscripten/web-template/vendor/fonts/Ubuntu-Bold.woff2 create mode 100644 etc/emscripten/web-template/vendor/fonts/Ubuntu-Italic.woff2 create mode 100644 etc/emscripten/web-template/vendor/fonts/Ubuntu-Regular.woff2 create mode 100644 etc/emscripten/web-template/vendor/fonts/UbuntuMono-Bold.woff2 create mode 100644 etc/emscripten/web-template/vendor/fonts/UbuntuMono-Regular.woff2 create mode 100644 etc/emscripten/web-template/vendor/gaplogo.svg create mode 100644 etc/emscripten/web-template/vendor/xterm-addon-fit.min.js create mode 100644 etc/emscripten/web-template/vendor/xterm-pty/index.js create mode 100644 etc/emscripten/web-template/vendor/xterm-pty/workerTools.js create mode 100644 etc/emscripten/web-template/vendor/xterm.css create mode 100644 etc/emscripten/web-template/vendor/xterm.min.js diff --git a/etc/emscripten/README.md b/etc/emscripten/README.md index 083de668b6..430c575415 100644 --- a/etc/emscripten/README.md +++ b/etc/emscripten/README.md @@ -2,7 +2,10 @@ Build GAP as a WebAssembly module and serve it as a self-contained website. The terminal interface uses [xterm-pty](https://github.com/mame/xterm-pty), -so the resulting page behaves like a normal GAP REPL. +so the resulting page behaves like a normal GAP REPL. The page is styled +to match (Ubuntu fonts, GAP logo, crimson +accents, dark-mode support) and adds a side panel for moving files in and +out of the browser session, an examples menu, and a restart button. ## Quick start @@ -50,6 +53,81 @@ TTY device so `tcsetattr()` reaches the line discipline. Both are sensitive to the toolchain version (a newer emsdk leaves `tcsetattr` unhonoured, so typed input is echoed twice), so re-test the REPL when changing emsdk. +## The `io` package + +The wasm build has no `dlopen`, so a package kernel extension cannot be +loaded the usual way. `build.sh` works around this for `io` by compiling +its single C file into the GAP kernel and registering it in the +static-module table (`src/compstat.c`), so `LoadKernelExtension("io")` +finds it without `dlopen`. This is the GASMAN-safe approach: `io` ends up +in the one wasm module, so ASYNCIFY's link-time pass instruments it +uniformly and `emscripten_scan_registers()` sees its frames (unlike a +dynamically loaded side module). The mechanism is detailed in the +comments in `build.sh` around the `IO_OBJ` block, with the registration +helper in `register_static_module.py`. + +`io` is the kernel dependency of several otherwise pure-GAP packages +(simpcomp, fr, rcwa, unitlib, …), so linking it in lets them load. Its +file/directory/time functions work; its socket/fork/select functions +compile but fail at runtime, since wasm has no such facilities. + +## The page: file transfer, examples, restart + +GAP runs with its working directory set to `/home/web_user` in the +virtual filesystem (the GAP tree itself sits at `/`, passed via `-l /`). +That directory starts empty, so everything in it is the user's: uploads +land there, and anything GAP creates there (`PrintTo`, `LogTo`, …) shows +up in the page's Files panel for download. + +The design is shaped by one constraint. Once GAP's `main()` starts, the +worker thread never returns to its event loop: every terminal operation +blocks in `Atomics.wait` inside xterm-pty's `TtyClient` until the main +thread responds. So `postMessage` *to* the worker is never delivered +after startup, while `postMessage` *from* the worker (the tty request +channel itself) always works. Hence: + +- **Uploads** go through a `SharedArrayBuffer` mailbox (chunked, see the + protocol comment in `gap-worker.js`; the sending side is in + `gap-ui.js`). The worker drains it at the start of every terminal + operation — the moments it is provably awake. An upload made while GAP + sits idle at its prompt therefore completes on the next terminal + activity; in particular, the Files panel's "insert `Read("file");`" + button pastes keystrokes whose processing drains the mailbox before + GAP ever sees the Enter, so the file is always in place in time. +- **Downloads** are pushed: when GAP asks for input (output has settled, + files are complete), the worker rescans `/home/web_user` and posts new + or changed files to the page, which caches the bytes. A download click + is served from that cache — it never has to ask the possibly-blocked + worker. This is also why a freshly written file only appears in the + panel once GAP is back at a prompt (or asks for input). +- Inserted commands (file hints and the examples menu) are pasted + *without* a newline; the user always presses Enter, so nothing is + auto-executed. + +### Cache invalidation across redeployments + +Library files are cached in the browser's IndexedDB and reused on later +visits without revalidation. To stop a redeployment from pairing a new +kernel with stale cached library files, `assemble-website.sh` writes a +fresh `build-id` file into the site; `gap-fs.js` compares it (fetched +with `cache: no-cache`) against the copy stored in the cache and +discards the cache when it differs. The page footer also has a "Reset +cached data" link that drops the cache and any registered service +worker and reloads — the escape hatch for any stuck client state. + +Known limitations, all consequences of the same architecture: + +- Ctrl-C cannot interrupt a running computation: there are no signals, + the main thread cannot reach the worker's wasm heap, and GAP cannot + poll JavaScript state while computing. The Restart button (which + terminates and respawns the worker) is the only escape from a runaway + computation. The Files panel keeps its cached entries across a + restart, still downloadable; inserting one re-uploads it first. +- User files do not persist across reloads or restarts (syncing them to + IndexedDB would need the worker's event loop, which is starved). +- The terminal is sized to the window before GAP starts; GAP does not + notice later resizes (no SIGWINCH), though xterm itself reflows. + ## Hosting The xterm-pty terminal uses `SharedArrayBuffer`, which browsers only allow @@ -71,12 +149,13 @@ re-fetches resources through a service worker that adds the headers). | ---- | ---- | | `build-in-docker.sh` | One-stop entry point. Builds the image, runs `build.sh` inside, then `assemble-website.sh`. | | `Dockerfile` | Pinned `emscripten/emsdk:3.1.23` with autotools, python3, bison/byacc/m4, and a baked-in copy of the GAP package distribution tarball at `/opt/gap-packages.tar.gz`. | -| `build.sh` | Configures and builds GMP, zlib, and GAP itself for wasm. | +| `build.sh` | Configures and builds GMP, zlib, and GAP itself for wasm. Also statically links the `io` package's kernel module into the kernel (see below). | | `assemble-website.sh` | Copies the build outputs and data directories (`pkg`, `lib`, `grp`, …) into `web-example/`. | | `generate_gap_fs_json.py` | Reads file paths on stdin, writes `gap-fs.json` (the manifest of every file in the virtual FS). | | `startup_manifest.json` | List of files to fetch eagerly at startup, captured from a real GAP run. Anything not in this list is fetched lazily on first read. See "Updating the startup manifest" below for how to refresh it. | | `serve.py` | Local server that adds the COOP/COEP headers. | -| `web-template/` | Static UI: `index.html`, the worker scripts, the FS init shim, and the COOP/COEP service worker for hosts where you can't set headers. | +| `web-template/` | Static UI: `index.html`, the page logic (`gap-ui.js`), the worker scripts, the FS init shim, and the COOP/COEP service worker for hosts where you can't set headers. | +| `web-template/vendor/` | Pinned local copies of xterm, xterm-pty, the fit addon, the GAP logo and the Ubuntu fonts, so the deployed site has no CDN dependency. See `web-template/vendor/README.md` for versions and how to update them. | ## Updating the startup manifest @@ -111,8 +190,8 @@ To regenerate it after such changes: `window.fetchedUrls` is an array of every unique URL the worker requested. Chrome/Firefox provide a `copy()` console helper: `copy(JSON.stringify(fetchedUrls))` puts the JSON on your clipboard. -5. Strip non-GAP-FS entries (`gap.js`, `gap.wasm`, `gap-fs.json`, the - xterm CDN URLs) and write the result to +5. Strip non-GAP-FS entries (`gap.js`, `gap.wasm`, `gap-fs.json`, and any + `vendor/` assets) and write the result to `etc/emscripten/startup_manifest.json` (so it's checked in and gets picked up by the next `assemble-website.sh`). A `jq` filter that keeps just GAP filesystem paths: diff --git a/etc/emscripten/assemble-website.sh b/etc/emscripten/assemble-website.sh index 12e6f6a83b..4816d23d2f 100755 --- a/etc/emscripten/assemble-website.sh +++ b/etc/emscripten/assemble-website.sh @@ -26,7 +26,7 @@ done rm -rf "$OUT_DIR" mkdir -p "$OUT_DIR" -cp "$SCRIPT_DIR"/web-template/* "$OUT_DIR"/ +cp -R "$SCRIPT_DIR"/web-template/* "$OUT_DIR"/ cp "$SCRIPT_DIR"/startup_manifest.json "$OUT_DIR"/ cp gap.js gap.wasm gap-fs.json "$OUT_DIR"/ # Emscripten only emits a separate gap.worker.js for pthread builds; this @@ -41,20 +41,27 @@ cp LICENSE COPYRIGHT "$OUT_DIR"/ # loaded (if listed in startup_manifest.json) or lazily fetched on first # read by Emscripten's createLazyFile. # -# -L dereferences symlinks so the output tree is self-contained (a setup -# where pkg/X is a symlink into a separate checkout still works). Some -# packages ship dangling symlinks as build artefacts (e.g. pkg/vole's -# rust/target/*.dSYM); cp prints those and exits non-zero but still copies -# everything else, so we don't let that abort the run. The assertion below -# catches a genuinely incomplete copy. +# tar -h dereferences symlinks so the output tree is self-contained (a +# setup where pkg/X is a symlink into a separate checkout still works); +# --exclude .git keeps such checkouts' git internals out of the shipped +# site. Some packages ship dangling symlinks as build artefacts (e.g. +# pkg/vole's rust/target/*.dSYM); tar reports those and exits non-zero +# but still copies everything else, so we don't let that abort the run. +# The assertion below catches a genuinely incomplete copy. for d in pkg lib grp tst doc hpcgap dev benchmark; do - cp -RL "$d" "$OUT_DIR"/ 2>/dev/null || true + tar -c -h --exclude '.git' -f - "$d" 2>/dev/null | tar -x -C "$OUT_DIR" -f - || true done # pkg/log holds package test logs (.log/.err/.out) that are never read at # runtime; keep them out of the shipped site. rm -rf "$OUT_DIR/pkg/log" +# A fresh id per assembled site. gap-fs.js compares it against the copy +# stored in the browser's IndexedDB cache and discards the cache when it +# differs, so a redeployment can never pair a new kernel with stale +# cached library files. +echo "$(date -u +%Y%m%dT%H%M%SZ)-$$" > "$OUT_DIR/build-id" + # The library bootstrap must be present, or GAP 404s during startup. if [[ ! -f "$OUT_DIR/lib/init.g" ]]; then echo "Error: lib/init.g missing from $OUT_DIR after copy." >&2 diff --git a/etc/emscripten/build.sh b/etc/emscripten/build.sh index d9197b04b6..432957888f 100755 --- a/etc/emscripten/build.sh +++ b/etc/emscripten/build.sh @@ -96,9 +96,17 @@ if [[ ! -f GNUmakefile ]] || ! grep -q '/emcc' GNUmakefile; then # emcc would be regenerated by a non-executable JS shim; stale .o # files have the wrong architecture. Configure regenerates build/. rm -rf build ffgen + # PTHREAD_CFLAGS/PTHREAD_LIBS: configure unconditionally adopts + # -pthread (for the sake of native kernel extensions, see configure.ac), + # but under emcc that flag enables full USE_PTHREADS mode — shared + # wasm memory, a helper worker, and a slow path when combined with + # ALLOW_MEMORY_GROWTH. GAP itself is single-threaded here, and + # emscripten's libc provides single-threaded pthread API stubs, so + # pre-seeding the variables makes AX_PTHREAD settle on "no flags". emconfigure ./configure ABI=32 \ --with-gmp="$AUX_PREFIX" \ --with-zlib="$AUX_PREFIX" \ + PTHREAD_CFLAGS=" " PTHREAD_LIBS=" " \ LDFLAGS="-s ASYNCIFY=1 -O2" fi @@ -125,13 +133,76 @@ fi # Copy host-built generated sources into place cp native-build/build/c_*.c native-build/build/ffdata.* src/ +# Statically link the 'io' package's kernel module into the GAP kernel. +# +# The wasm build has no dlopen, so a package kernel extension cannot be +# loaded the usual way. But GAP's loader already supports STATIC modules: +# LoadKernelExtension("io") (in io's init.g) checks SHOW_STAT() -- the +# list of names in CompInitFuncs[] (src/compstat.c) -- and loads a match +# without dlopen (see lib/files.gd). So we compile io's single C file into +# the kernel and add it to that table; no change to GAP's loader or io's +# GAP code is needed. This is the safe approach for GASMAN: io ends up in +# the one wasm module, so ASYNCIFY's link-time pass instruments it +# uniformly with the rest of the kernel and emscripten_scan_registers +# sees its frames (unlike a dlopen'd side module). +# +# io is the kernel dependency of several otherwise pure-GAP packages +# (simpcomp, fr, rcwa, unitlib, ...). Its socket/fork/select-based +# functions compile (emscripten declares the symbols) but fail at runtime +# under wasm; its file/directory/time functions work. +IO_OBJ="" +if [[ -d pkg/io ]]; then + IO_PKG="$PWD/pkg/io" + # io's configure (autoconf feature probe) writes gen/pkgconfig.h, which + # io.c needs. FIND_GAP may fail without a fully built GAP in $BASEDIR + # and exit non-zero, but pkgconfig.h is still generated by then, so we + # tolerate the exit code and assert on the file instead. + ( + cd "$IO_PKG" + [[ -f configure ]] || ./autogen.sh + emconfigure ./configure --with-gaproot="$BASEDIR" || true + ) + if [[ ! -f "$IO_PKG/gen/pkgconfig.h" ]]; then + echo "Error: io's pkgconfig.h was not generated; cannot link io." >&2 + exit 1 + fi + # io.c (via gap_all.h) includes generated kernel headers. The normal + # build generates these before compiling any object; since we compile + # io.o ahead of that, generate them first. + emmake make build/version.h build/config.h + # Compile io.c, renaming its generic Init__Dynamic to the unique + # Init__io that the static-module table references. ASYNCIFY is a + # link-time pass, so it is not (and must not be) given here. + emcc -m32 -c "$IO_PKG/src/io.c" -o "$AUX_BUILD/io.o" \ + -DInit__Dynamic=Init__io \ + -Isrc -Ibuild -Isrc/extra \ + -I"$IO_PKG/gen" -I"$IO_PKG/src" \ + -I"$AUX_PREFIX/include" \ + -fPIC -fno-strict-aliasing -O2 + python3 etc/emscripten/register_static_module.py io src/compstat.c + IO_OBJ="$AUX_BUILD/io.o" +fi + # Build the file list that will be served. -L follows symlinks so that # users' local development setups (e.g. replacing pkg/foo with a symlink # to a git checkout under git/foo) are picked up; -type f then drops any # symlinks themselves. find -L pkg lib grp tst doc hpcgap dev benchmark -type f ! -path 'pkg/log/*' \ + ! -path '*/.git/*' \ | python3 etc/emscripten/generate_gap_fs_json.py +# Emscripten only emits gap.worker.js for pthread builds; remove any +# leftover from a previous configuration so assemble-website.sh can't +# ship a stale one. +rm -f gap.worker.js + +# Memory: start small and grow on demand (sbrk stays contiguous, which +# GASMAN's workspace extension requires, since wasm memory grows in +# place). A 2GB up-front allocation was refused outright on iOS. +# $IO_OBJ (if set) is the statically-linked io module object; it goes on +# the link line, where the Init__io reference from src/compstat.c pulls it +# in. LDFLAGS flows into GAP_LDFLAGS (see Makefile.rules), which is part of +# the final link command. emmake make -j"$JOBS" \ - LDFLAGS="-lidbfs.js -s ASYNCIFY=1 -sTOTAL_STACK=32mb -sASYNCIFY_STACK_SIZE=32000000 -sINITIAL_MEMORY=2048mb -O2" \ + LDFLAGS="-lidbfs.js -s ASYNCIFY=1 -sTOTAL_STACK=32mb -sASYNCIFY_STACK_SIZE=32000000 -sINITIAL_MEMORY=256mb -sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=2048mb $IO_OBJ -O2" \ EXEEXT=".html" diff --git a/etc/emscripten/register_static_module.py b/etc/emscripten/register_static_module.py new file mode 100644 index 0000000000..59fc281f23 --- /dev/null +++ b/etc/emscripten/register_static_module.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +"""Register a package kernel module as a static module in src/compstat.c. + +GAP's static-module table (CompInitFuncs[] in src/compstat.c) is the list +of init functions that SHOW_STAT() reports; LoadKernelExtension finds a +module there and loads it without dlopen (which the wasm build lacks). +This adds an entry for a module whose init function has been renamed to +Init__ (via -DInit__Dynamic=Init__ when compiling it). + +Idempotent: running twice for the same module is a no-op. Usage: + register_static_module.py [path/to/compstat.c] +""" +import re +import sys + +name = sys.argv[1] +path = sys.argv[2] if len(sys.argv) > 2 else "src/compstat.c" +init = "Init__" + name + +src = open(path).read() +if init in src: + sys.exit(0) # already registered + +# Add the extern declaration after the last existing one. +externs = list(re.finditer(r"extern StructInitInfo \* Init__\w+\(void\);\n", src)) +if not externs: + sys.exit("register_static_module: no extern declarations found in " + path) +at = externs[-1].end() +src = src[:at] + "extern StructInitInfo * %s(void);\n" % init + src[at:] + +# Add the entry before the 0 terminator of CompInitFuncs[]. +src, n = re.subn(r"\n(\s*)0(,?\n\};)", r"\n\1%s,\n\g<1>0\2" % init, src, count=1) +if n != 1: + sys.exit("register_static_module: could not find CompInitFuncs terminator in " + path) + +open(path, "w").write(src) diff --git a/etc/emscripten/serve.py b/etc/emscripten/serve.py index 7d089f0c54..5afe9cb8af 100755 --- a/etc/emscripten/serve.py +++ b/etc/emscripten/serve.py @@ -18,6 +18,9 @@ class CrossOriginIsolatedHandler(http.server.SimpleHTTPRequestHandler): def end_headers(self): self.send_header("Cross-Origin-Opener-Policy", "same-origin") self.send_header("Cross-Origin-Embedder-Policy", "require-corp") + # Without this, browsers cache the UI files heuristically and + # edits to web-example/ don't show up on reload. + self.send_header("Cache-Control", "no-cache") super().end_headers() diff --git a/etc/emscripten/web-template/coi-serviceworker.js b/etc/emscripten/web-template/coi-serviceworker.js index 2e76c2137d..9901474cc3 100755 --- a/etc/emscripten/web-template/coi-serviceworker.js +++ b/etc/emscripten/web-template/coi-serviceworker.js @@ -1,4 +1,4 @@ -/*! coi-serviceworker v0.1.6 - Guido Zuidhof, licensed under MIT */ +/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */ let coepCredentialless = false; if (typeof window === 'undefined') { self.addEventListener("install", () => self.skipWaiting()); @@ -43,6 +43,9 @@ if (typeof window === 'undefined') { newHeaders.set("Cross-Origin-Embedder-Policy", coepCredentialless ? "credentialless" : "require-corp" ); + if (!coepCredentialless) { + newHeaders.set("Cross-Origin-Resource-Policy", "cross-origin"); + } newHeaders.set("Cross-Origin-Opener-Policy", "same-origin"); return new Response(response.body, { @@ -57,23 +60,46 @@ if (typeof window === 'undefined') { } else { (() => { + const reloadedBySelf = window.sessionStorage.getItem("coiReloadedBySelf"); + window.sessionStorage.removeItem("coiReloadedBySelf"); + const coepDegrading = (reloadedBySelf == "coepdegrade"); + // You can customize the behavior of this script through a global `coi` variable. const coi = { - shouldRegister: () => true, + shouldRegister: () => !reloadedBySelf, shouldDeregister: () => false, - coepCredentialless: () => false, + coepCredentialless: () => true, + coepDegrade: () => true, doReload: () => window.location.reload(), quiet: false, ...window.coi }; const n = navigator; + const controlling = n.serviceWorker && n.serviceWorker.controller; + + // Record the failure if the page is served by serviceWorker. + if (controlling && !window.crossOriginIsolated) { + window.sessionStorage.setItem("coiCoepHasFailed", "true"); + } + const coepHasFailed = window.sessionStorage.getItem("coiCoepHasFailed"); - if (n.serviceWorker && n.serviceWorker.controller) { + if (controlling) { + // Reload only on the first failure. + const reloadToDegrade = coi.coepDegrade() && !( + coepDegrading || window.crossOriginIsolated + ); n.serviceWorker.controller.postMessage({ type: "coepCredentialless", - value: coi.coepCredentialless(), + value: (reloadToDegrade || coepHasFailed && coi.coepDegrade()) + ? false + : coi.coepCredentialless(), }); + if (reloadToDegrade) { + !coi.quiet && console.log("Reloading page to degrade COEP."); + window.sessionStorage.setItem("coiReloadedBySelf", "coepdegrade"); + coi.doReload("coepdegrade"); + } if (coi.shouldDeregister()) { n.serviceWorker.controller.postMessage({ type: "deregister" }); @@ -89,27 +115,32 @@ if (typeof window === 'undefined') { return; } - // In some environments (e.g. Chrome incognito mode) this won't be available - if (n.serviceWorker) { - n.serviceWorker.register(window.document.currentScript.src).then( - (registration) => { - !coi.quiet && console.log("COOP/COEP Service Worker registered", registration.scope); + // In some environments (e.g. Firefox private mode) this won't be available + if (!n.serviceWorker) { + !coi.quiet && console.error("COOP/COEP Service Worker not registered, perhaps due to private mode."); + return; + } + + n.serviceWorker.register(window.document.currentScript.src).then( + (registration) => { + !coi.quiet && console.log("COOP/COEP Service Worker registered", registration.scope); - registration.addEventListener("updatefound", () => { - !coi.quiet && console.log("Reloading page to make use of updated COOP/COEP Service Worker."); - coi.doReload(); - }); + registration.addEventListener("updatefound", () => { + !coi.quiet && console.log("Reloading page to make use of updated COOP/COEP Service Worker."); + window.sessionStorage.setItem("coiReloadedBySelf", "updatefound"); + coi.doReload(); + }); - // If the registration is active, but it's not controlling the page - if (registration.active && !n.serviceWorker.controller) { - !coi.quiet && console.log("Reloading page to make use of COOP/COEP Service Worker."); - coi.doReload(); - } - }, - (err) => { - !coi.quiet && console.error("COOP/COEP Service Worker failed to register:", err); + // If the registration is active, but it's not controlling the page + if (registration.active && !n.serviceWorker.controller) { + !coi.quiet && console.log("Reloading page to make use of COOP/COEP Service Worker."); + window.sessionStorage.setItem("coiReloadedBySelf", "notcontrolling"); + coi.doReload(); } - ); - } + }, + (err) => { + !coi.quiet && console.error("COOP/COEP Service Worker failed to register:", err); + } + ); })(); } diff --git a/etc/emscripten/web-template/gap-fs.js b/etc/emscripten/web-template/gap-fs.js index ca8ea4f23d..5ad7eaac01 100644 --- a/etc/emscripten/web-template/gap-fs.js +++ b/etc/emscripten/web-template/gap-fs.js @@ -30,6 +30,13 @@ self.Module.preRun = self.Module.preRun || []; self.Module.preRun.push(function() { addRunDependency('gap_fs_init'); + // GAP starts in /home/web_user, which stays empty here, so anything + // under it is user-created (uploads, PrintTo output, ...). That keeps + // user files cleanly apart from the GAP tree at /; gap-worker.js + // passes "-l /" so GAP still finds its root. + FS.mkdirTree('/home/web_user'); + FS.chdir('/home/web_user'); + async function initFS() { try { const mapRes = await fetch('gap-fs.json'); @@ -51,14 +58,52 @@ self.Module.preRun.push(function() { FS.mount(IDBFS, {}, '/gap_idb_cache'); FS.syncfs(true, async function(err) { + var needsSave = false; + + // Discard the cache when the site was redeployed: a + // library file cached from one build must never be + // paired with the kernel of another. build-id is + // written by assemble-website.sh; a site without one + // (e.g. hand-assembled) keeps its cache indefinitely. + var storedId = null; + try { + storedId = new TextDecoder().decode( + FS.readFile('/gap_idb_cache/.build-id')); + } catch (e) {} + var buildId = null; + try { + const idRes = await fetch('build-id', { cache: 'no-cache' }); + if (idRes.ok) buildId = (await idRes.text()).trim(); + } catch (e) {} + if (buildId === null) { + console.info("gap-fs: no build-id served; reusing any cached files"); + } else if (storedId !== buildId) { + if (storedId !== null) { + console.info("gap-fs: site updated (" + storedId + + " -> " + buildId + "); discarding cached files"); + } + (function wipe(dir) { + FS.readdir(dir).forEach(function(name) { + if (name === '.' || name === '..') return; + var p = dir + '/' + name; + if (FS.isDir(FS.stat(p).mode)) { + wipe(p); + FS.rmdir(p); + } else { + FS.unlink(p); + } + }); + })('/gap_idb_cache'); + FS.writeFile('/gap_idb_cache/.build-id', buildId); + needsSave = true; + } + fileList.forEach(function(appPath) { var parts = appPath.split('/'); parts.pop(); var parentDir = '/' + parts.join('/'); try { FS.mkdirTree('/gap_idb_cache' + parentDir); } catch(e) {} }); - - var needsSave = false; var startupSet = new Set(); try { diff --git a/etc/emscripten/web-template/gap-ui.js b/etc/emscripten/web-template/gap-ui.js new file mode 100644 index 0000000000..53c8f17317 --- /dev/null +++ b/etc/emscripten/web-template/gap-ui.js @@ -0,0 +1,429 @@ +// Main-thread logic for the GAP-in-the-browser page: terminal/worker +// lifecycle (including restart), the upload mailbox sender, the files +// panel, the examples menu, and the loading progress notice. +// +// The worker side (gap-worker.js) explains the central constraint: after +// startup the worker only runs during terminal operations, blocking in +// Atomics.wait the rest of the time. So uploads go through a +// SharedArrayBuffer mailbox the worker drains on terminal activity, and +// the worker pushes copies of every user file to this thread, so +// downloads are served from a local cache and never need to ask a +// (possibly blocked) worker. + +"use strict"; + +// ---- upload mailbox protocol; keep in sync with gap-worker.js ---- +const MB_STATE = 0, MB_LEN = 1, MB_FLAGS = 2; +const MB_IDLE = 0, MB_READY = 1, MB_CONSUMED = 2; +const MB_FLAG_HEADER = 1, MB_FLAG_FINAL = 2, MB_FLAG_END = 4; +const MB_CTRL_BYTES = 16; +const MB_DATA_BYTES = 1 << 20; + +// Multi-line examples: every line except the last is submitted as it is +// pasted (the newline acts as Enter), so earlier lines run immediately — +// keep them to setup (silenced with ";;" or printing the definition); +// only the last line waits for the user's Enter. +const EXAMPLES = [ + { label: "Intersect two permutation groups", + code: 'G := Group((1,2,3)(4,5,6), (1,4), (2,5), (3,6));\n' + + 'H := Group((1,2,4,6), (4,6));\n' + + 'Intersection(G, H);' }, + { label: "Character table of A5", + code: 'Display(CharacterTable(AlternatingGroup(5)));' }, + { label: "The groups of order 12", + code: 'List(AllSmallGroups(12), StructureDescription);' }, + { label: "Factorise a Fermat number", + code: 'Factors(2^64 + 1);' }, + { label: "A finitely presented group", + code: 'F := FreeGroup("a", "b");;\nG := F / [F.1^2, F.2^3, (F.1*F.2)^5];; Size(G);' }, +]; + +const loadingEl = document.getElementById("loading"); +const unsupportedEl = document.getElementById("unsupported"); +const terminalEl = document.getElementById("terminal"); +const restartBtn = document.getElementById("restart"); +const uploadInput = document.getElementById("upload-input"); +const uploadBtn = document.getElementById("upload-button"); +const fileListEl = document.getElementById("file-list"); +const fileEmptyEl = document.getElementById("files-empty"); +const examplesEl = document.getElementById("example-list"); + +// URLs reported by gap-fs.js's fetch/XHR instrumentation, for rebuilding +// startup_manifest.json (see README.md). Inspect from the devtools +// console with copy(JSON.stringify(fetchedUrls)). +window.fetchedUrls = []; +const fetchedSet = new Set(); + +// Number of files the startup manifest will fetch on a cold visit, for +// the progress notice. 0 (missing/empty manifest) keeps the generic text. +let manifestTotal = 0; +fetch("startup_manifest.json") + .then((r) => (r.ok ? r.json() : [])) + .then((list) => { manifestTotal = list.length; }) + .catch(() => {}); + +// The files panel cache: path -> entry. Entries survive a session restart +// (status "previous"): the bytes are still here, so they stay +// downloadable, and inserting their Read command first re-uploads them +// into the new session. +// { size, data: Uint8Array, status: "transferring"|"ready"|"previous" } +const fileEntries = new Map(); + +// Per-session state; replaced wholesale by startSession() so that any +// in-flight async sender from a dead session aborts cleanly. +let session = null; + +function gapQuote(path) { + return '"' + path.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"'; +} + +function humanSize(n) { + if (n < 1024) return n + " B"; + if (n < 1024 * 1024) return (n / 1024).toFixed(1) + " kB"; + return (n / (1024 * 1024)).toFixed(1) + " MB"; +} + +// Paste text at GAP's prompt. Deliberately no trailing newline: the user +// presses Enter, so nothing is ever auto-executed. +function insertAtPrompt(text) { + if (session === null) return; + session.xterm.paste(text); + session.xterm.focus(); +} + +// --------------------------------------------------------------------- +// Upload sender. Writes one chunk whenever the worker has consumed the +// previous one; never blocks the main thread (Atomics.wait is forbidden +// here, so it uses Atomics.waitAsync where available and polling +// otherwise). The worker only drains on terminal activity, so a transfer +// started while GAP sits at its prompt completes on the next keystroke — +// in particular, the keystrokes of a pasted Read command arrive after +// the drain runs, so the file is always in place before Enter. + +function waitMailboxState(s, want) { + return new Promise((resolve, reject) => { + const check = () => { + if (s.dead) { + reject(new Error("session restarted")); + return; + } + const cur = Atomics.load(s.mbCtrl, MB_STATE); + if (cur === want) { + resolve(); + return; + } + if (Atomics.waitAsync) { + const r = Atomics.waitAsync(s.mbCtrl, MB_STATE, cur, 1000); + if (r.async) r.value.then(check); + else check(); + } else { + setTimeout(check, 10); + } + }; + check(); + }); +} + +function writeChunk(s, bytes, flags) { + s.mbData.set(bytes, 0); + s.mbCtrl[MB_LEN] = bytes.length; + s.mbCtrl[MB_FLAGS] = flags; + Atomics.store(s.mbCtrl, MB_STATE, MB_READY); + Atomics.notify(s.mbCtrl, MB_STATE); +} + +// files: [{ name, data: Uint8Array }] +async function sendFiles(files) { + const s = session; + for (const f of files) { + fileEntries.set(f.name, { size: f.data.length, data: f.data, + status: "transferring" }); + s.uploadQueue.push(f); + } + renderFiles(); + if (s.senderActive) return; + s.senderActive = true; + try { + await waitMailboxState(s, MB_IDLE); + while (s.uploadQueue.length > 0) { + const f = s.uploadQueue.shift(); + const header = new TextEncoder().encode( + JSON.stringify({ name: f.name, size: f.data.length })); + writeChunk(s, header, MB_FLAG_HEADER); + await waitMailboxState(s, MB_CONSUMED); + let off = 0; + do { + const n = Math.min(MB_DATA_BYTES, f.data.length - off); + const last = off + n >= f.data.length; + writeChunk(s, f.data.subarray(off, off + n), + last ? MB_FLAG_FINAL : 0); + off += n; + await waitMailboxState(s, MB_CONSUMED); + } while (off < f.data.length); + } + // Close the session; the worker hands the mailbox back as MB_IDLE. + writeChunk(s, new Uint8Array(0), MB_FLAG_END); + } catch (e) { + // Only a restart gets here; the entries were already marked + // "previous" by the restart handler. + if (!s.dead) throw e; + } finally { + s.senderActive = false; + } +} + +// --------------------------------------------------------------------- +// Files panel + +function downloadEntry(path) { + const entry = fileEntries.get(path); + const blob = new Blob([entry.data]); + const a = document.createElement("a"); + a.href = URL.createObjectURL(blob); + a.download = path.split("/").pop(); + a.click(); + URL.revokeObjectURL(a.href); +} + +function insertEntry(path) { + const entry = fileEntries.get(path); + if (entry.status === "previous") { + // From a previous session: put it back first. The re-upload drains + // before the pasted command's Enter can be processed. + sendFiles([{ name: path, data: entry.data }]); + } + insertAtPrompt("Read(" + gapQuote(path) + ");"); +} + +function renderFiles() { + fileListEl.textContent = ""; + fileEmptyEl.style.display = fileEntries.size === 0 ? "" : "none"; + const paths = Array.from(fileEntries.keys()).sort(); + for (const path of paths) { + const entry = fileEntries.get(path); + const li = document.createElement("li"); + + const nameSpan = document.createElement("span"); + nameSpan.className = "file-name"; + nameSpan.textContent = path; + nameSpan.title = path; + + const metaSpan = document.createElement("span"); + metaSpan.className = "file-meta"; + metaSpan.textContent = humanSize(entry.size) + + (entry.status === "transferring" ? " · sending…" + : entry.status === "failed" ? " · failed" + : entry.status === "previous" ? " · previous session" : ""); + + const insertB = document.createElement("button"); + insertB.className = "icon-button"; + insertB.textContent = "↳"; + insertB.title = "Insert Read(" + gapQuote(path) + "); at the prompt" + + (entry.status === "previous" ? " (re-uploads the file first)" : ""); + insertB.addEventListener("click", () => insertEntry(path)); + + const downloadB = document.createElement("button"); + downloadB.className = "icon-button"; + downloadB.textContent = "⬇"; + downloadB.title = "Download " + path; + downloadB.addEventListener("click", () => downloadEntry(path)); + + const text = document.createElement("div"); + text.className = "file-text"; + text.append(nameSpan, metaSpan); + li.append(text, insertB, downloadB); + fileListEl.append(li); + } +} + +uploadBtn.addEventListener("click", () => uploadInput.click()); +uploadInput.addEventListener("change", async () => { + const files = []; + for (const f of uploadInput.files) { + // Basename only: uploads land directly in GAP's working directory. + const name = f.name.split(/[/\\]/).pop(); + if (name === "") continue; + const data = new Uint8Array(await f.arrayBuffer()); + files.push({ name: name, data: data }); + } + uploadInput.value = ""; + if (files.length > 0) sendFiles(files); +}); + +// --------------------------------------------------------------------- +// Examples + +for (const ex of EXAMPLES) { + const li = document.createElement("li"); + const b = document.createElement("button"); + b.className = "example-button"; + b.textContent = ex.label; + b.title = ex.code; + b.addEventListener("click", () => insertAtPrompt(ex.code)); + li.append(b); + examplesEl.append(li); +} + +// --------------------------------------------------------------------- +// Session lifecycle + +function handleWorkerMessage(ev) { + const data = ev.data; + if (!data || !data.type) return; + switch (data.type) { + case "gap-fetched": + if (!fetchedSet.has(data.url)) { + fetchedSet.add(data.url); + window.fetchedUrls.push(data.url); + if (/^(pkg|lib|grp|tst|doc|hpcgap|dev|benchmark)\//.test(data.url)) { + session.fetchCount++; + if (!session.started) { + const progress = "fetched " + session.fetchCount + + (manifestTotal > 0 ? " of ~" + manifestTotal : "") + " files"; + loadingEl.textContent = "Loading GAP… " + progress + "."; + // \r keeps overwriting one progress line in the terminal. + session.xterm.write("\rLoading GAP… " + progress); + } + } + } + break; + case "gap-user-files": + for (const f of data.changed) { + fileEntries.set(f.path, { size: f.size, data: f.data, + status: "ready" }); + } + for (const p of data.removed) { + // Deleted inside GAP; drop it from the panel too. + fileEntries.delete(p); + } + renderFiles(); + break; + case "gap-file-uploaded": { + const entry = fileEntries.get(data.name); + if (entry && entry.status === "transferring") entry.status = "ready"; + renderFiles(); + break; + } + case "gap-file-error": + console.error("Upload failed in worker:", data); + for (const entry of fileEntries.values()) { + if (entry.status === "transferring") entry.status = "failed"; + } + renderFiles(); + break; + } +} + +function startSession() { + loadingEl.style.display = ""; + loadingEl.textContent = "Loading GAP… The first visit downloads several " + + "tens of megabytes; later visits are cached by your browser and " + + "start much faster."; + + const xterm = new Terminal({ + fontFamily: '"Ubuntu Mono", Menlo, Consolas, monospace', + fontSize: 15, + cursorBlink: true, + theme: { background: "#1d1d1d", foreground: "#e6e6e6" }, + }); + const fitAddon = new FitAddon.FitAddon(); + xterm.loadAddon(fitAddon); + xterm.open(terminalEl); + fitAddon.fit(); + + const { master, slave } = openpty(); + xterm.loadAddon(master); + + const mailbox = new SharedArrayBuffer(MB_CTRL_BYTES + MB_DATA_BYTES); + const worker = new Worker("gap-worker.js"); + worker.postMessage({ type: "gap-init", mailbox: mailbox }); + + session = { + xterm: xterm, + fitAddon: fitAddon, + master: master, + slave: slave, + worker: worker, + mbCtrl: new Int32Array(mailbox, 0, 4), + mbData: new Uint8Array(mailbox, MB_CTRL_BYTES), + uploadQueue: [], + senderActive: false, + fetchCount: 0, + started: false, + dead: false, + }; + const s = session; + + // GAP's first terminal output arrives as the worker's first "write" + // tty request. Detect it here (this listener is registered before + // TtyServer.start assigns worker.onmessage, so it runs first) and + // reset the terminal, so the waiting/progress text below is wiped + // and the GAP banner starts on a clean screen. + worker.addEventListener("message", (ev) => { + const d = ev.data; + if (d && d.ttyRequestType === "write" && !s.started) { + s.started = true; + s.xterm.reset(); + loadingEl.style.display = "none"; + } + }); + + session.ttyServer = new TtyServer(slave); + session.ttyServer.start(worker, handleWorkerMessage); + + xterm.write( + "\x1b[2mPlease wait — downloading and starting GAP.\r\n" + + "The first visit can take a few minutes; repeat visits are cached " + + "by your browser and start much faster.\x1b[0m\r\n\r\n"); +} + +function restartSession() { + session.dead = true; + session.worker.terminate(); + session.xterm.dispose(); + for (const entry of fileEntries.values()) { + // The session's filesystem is gone, but our cached bytes are not. + entry.status = "previous"; + } + renderFiles(); + startSession(); +} + +window.addEventListener("resize", () => { + if (session !== null) session.fitAddon.fit(); +}); + +restartBtn.addEventListener("click", () => { + if (session !== null) restartSession(); +}); + +// Escape hatch for stale state: drop the IndexedDB file cache and any +// registered service worker, then reload from the network. (gap-fs.js +// also discards the cache automatically when the site's build-id +// changes; this covers everything else.) +document.getElementById("reset-site").addEventListener("click", async (ev) => { + ev.preventDefault(); + if (session !== null) { + session.dead = true; + session.worker.terminate(); + } + if (navigator.serviceWorker) { + const regs = await navigator.serviceWorker.getRegistrations(); + await Promise.all(regs.map((r) => r.unregister())); + } + await new Promise((resolve) => { + const req = indexedDB.deleteDatabase("/gap_idb_cache"); + req.onsuccess = req.onerror = req.onblocked = resolve; + }); + location.reload(); +}); + +// Without SharedArrayBuffer the worker can't talk to the page +// synchronously; xterm-pty would stall on every read. +if (typeof SharedArrayBuffer === "undefined") { + loadingEl.style.display = "none"; + unsupportedEl.style.display = "block"; +} else { + renderFiles(); + startSession(); +} diff --git a/etc/emscripten/web-template/gap-worker.js b/etc/emscripten/web-template/gap-worker.js index 9b71069a9f..c87864c12b 100755 --- a/etc/emscripten/web-template/gap-worker.js +++ b/etc/emscripten/web-template/gap-worker.js @@ -1,9 +1,216 @@ -importScripts("https://cdn.jsdelivr.net/npm/xterm-pty@0.9.4/workerTools.js"); +// GAP worker: loads the wasm module and wires its TTY to the xterm-pty +// server on the main thread. +// +// Once GAP's main() starts, this thread never returns to the event loop: +// every terminal operation goes through TtyClient, which posts a request +// and then blocks in Atomics.wait until the main thread responds. So +// postMessage TO this worker is never delivered after startup. File +// uploads therefore use a SharedArrayBuffer mailbox (sending side in +// gap-ui.js), drained at the top of every terminal operation — the +// moments this thread is provably awake. postMessage FROM this worker is +// the tty request channel itself, so it always works; downloads are +// pushed to the page that way. + +importScripts("vendor/xterm-pty/workerTools.js"); + +// --------------------------------------------------------------------- +// Upload mailbox (main thread -> worker). +// +// Layout: Int32Array ctrl[4] in bytes [0,16), then a Uint8Array data +// area. ctrl[MB_STATE] is the handshake word: the main thread may only +// write a chunk when it is MB_IDLE (new session) or MB_CONSUMED (next +// chunk), and sets it to MB_READY; the worker consumes the chunk and +// sets MB_CONSUMED, or MB_IDLE after the session-closing END chunk. +// +// A session is one or more files, each sent as a HEADER chunk (JSON +// {name, size}) followed by data chunks with the last flagged FINAL, +// and is terminated by an empty END chunk. The worker consumes a whole +// session in one drainMailbox() call, blocking in Atomics.wait between +// chunks (the main thread never blocks; it polls with Atomics.waitAsync +// or setTimeout). Keep the constants in sync with gap-ui.js. + +const MB_STATE = 0, MB_LEN = 1, MB_FLAGS = 2; +const MB_IDLE = 0, MB_READY = 1, MB_CONSUMED = 2; +const MB_FLAG_HEADER = 1, MB_FLAG_FINAL = 2, MB_FLAG_END = 4; +const MB_CTRL_BYTES = 16; + +let mbCtrl = null; +let mbData = null; + +const USER_DIR = "/home/web_user"; + +function drainMailbox() { + if (mbCtrl === null || Atomics.load(mbCtrl, MB_STATE) !== MB_READY) + return; + + let cur = null; // file in transit: { name, buf, off } + for (;;) { + const flags = mbCtrl[MB_FLAGS]; + const len = mbCtrl[MB_LEN]; + + if (flags & MB_FLAG_END) { + // Session closed; hand the mailbox back to the main thread. + Atomics.store(mbCtrl, MB_STATE, MB_IDLE); + Atomics.notify(mbCtrl, MB_STATE); + return; + } + + if (flags & MB_FLAG_HEADER) { + // slice (not subarray): TextDecoder rejects views backed by + // a SharedArrayBuffer, so decode from a non-shared copy. + const header = JSON.parse( + new TextDecoder().decode(mbData.slice(0, len))); + cur = { + name: header.name, + buf: new Uint8Array(header.size), + off: 0, + }; + } else { + cur.buf.set(mbData.subarray(0, len), cur.off); + cur.off += len; + if (flags & MB_FLAG_FINAL) { + if (cur.off !== cur.buf.length) + throw new Error("gap-worker: upload of " + cur.name + + " ended at " + cur.off + " of " + cur.buf.length + + " bytes"); + FS.writeFile(USER_DIR + "/" + cur.name, cur.buf); + postMessage({ type: "gap-file-uploaded", name: cur.name }); + cur = null; + } + } + + Atomics.store(mbCtrl, MB_STATE, MB_CONSUMED); + Atomics.notify(mbCtrl, MB_STATE); + + // Wait for the main thread to publish the next chunk. It answers + // within its event-loop latency; a long stall means the page side + // died mid-transfer, and hanging GAP forever on that would be + // worse than abandoning the upload loudly. + while (Atomics.load(mbCtrl, MB_STATE) !== MB_READY) { + const r = Atomics.wait(mbCtrl, MB_STATE, MB_CONSUMED, 30000); + if (r === "timed-out") { + console.error("gap-worker: upload stalled; abandoning transfer"); + postMessage({ type: "gap-file-error", + name: cur === null ? null : cur.name, + error: "transfer stalled" }); + Atomics.store(mbCtrl, MB_STATE, MB_IDLE); + return; + } + } + } +} + +// --------------------------------------------------------------------- +// Download push (worker -> main thread). +// +// GAP starts in USER_DIR, which begins empty, so everything under it is +// user-created (or uploaded). Whenever GAP asks for terminal input — +// i.e. output has settled and any files it wrote are complete — walk the +// directory and push new/changed files to the page, which caches the +// bytes so a download click never needs the (possibly blocked) worker. +// +// No throttling: the scan before GAP blocks for input is the LAST chance +// to notice a new file (nothing re-triggers while it is blocked), so a +// time-based throttle would skip exactly the scan that matters. The walk +// is stat-only and the directory is small; files are only read (and +// posted) when size/mtime changed. + +const knownFiles = new Map(); // relative path -> "size:mtime" key + +function scanUserFiles() { + const changedPaths = []; + const seen = new Set(); + (function walk(dir, rel) { + for (const name of FS.readdir(dir)) { + if (name === "." || name === "..") + continue; + const path = dir + "/" + name; + const st = FS.stat(path); + const relPath = rel === "" ? name : rel + "/" + name; + if (FS.isDir(st.mode)) { + walk(path, relPath); + } else if (FS.isFile(st.mode)) { + seen.add(relPath); + const key = st.size + ":" + st.mtime.getTime(); + if (knownFiles.get(relPath) !== key) { + knownFiles.set(relPath, key); + changedPaths.push(relPath); + } + } + } + })(USER_DIR, ""); + + const removed = []; + for (const p of knownFiles.keys()) { + if (!seen.has(p)) { + knownFiles.delete(p); + removed.push(p); + } + } + + if (changedPaths.length === 0 && removed.length === 0) + return; + const changed = changedPaths.map((p) => { + const data = FS.readFile(USER_DIR + "/" + p); // returns a fresh copy + return { path: p, size: data.length, data: data }; + }); + postMessage({ type: "gap-user-files", changed: changed, removed: removed }, + changed.map((f) => f.data.buffer)); +} + +// --------------------------------------------------------------------- +// Startup. Two messages, in order: the page's gap-init (carrying the +// upload mailbox), then the tty SharedArrayBuffer that TtyServer.start() +// posts. Everything else happens inside terminal-operation hooks. onmessage = (msg) => { - // Prepare the Module object BEFORE importing gap.js - self.Module = self.Module || {}; - importScripts("gap-fs.js"); - importScripts("gap.js"); - emscriptenHack(new TtyClient(msg.data)); + if (msg.data && msg.data.type === "gap-init") { + mbCtrl = new Int32Array(msg.data.mailbox, 0, 4); + mbData = new Uint8Array(msg.data.mailbox, MB_CTRL_BYTES); + return; + } + + // Prepare the Module object BEFORE importing gap.js. The FS init in + // gap-fs.js chdirs to USER_DIR, so tell GAP its root explicitly. + self.Module = self.Module || {}; + self.Module.arguments = ["-l", "/"]; + importScripts("gap-fs.js"); + importScripts("gap.js"); + + // Hook every terminal operation: drain pending uploads first (so a + // pasted Read("file.g"); line always finds its file — the paste's + // own keystrokes trigger the drain before GAP sees the newline), and + // scan for new user files when GAP is asking for input. + // + // An exception escaping these hooks would propagate into the wasm + // stack, where emscripten's invoke trampolines can swallow it with + // no console output (observed with TextDecoder throwing on a shared + // buffer) — leaving GAP dead and the failure invisible. Report + // loudly before letting it propagate. + const fileTransferHook = (scan) => { + try { + drainMailbox(); + if (scan) scanUserFiles(); + } catch (e) { + console.error("gap-worker: file transfer hook failed:", e); + postMessage({ type: "gap-file-error", name: null, + error: String(e) }); + throw e; + } + }; + const client = new TtyClient(msg.data); + const hooked = Object.create(client); + hooked.onRead = (length) => { + fileTransferHook(true); + return client.onRead(length); + }; + hooked.onWaitForReadable = (timeout) => { + fileTransferHook(true); + return client.onWaitForReadable(timeout); + }; + hooked.onWrite = (buf) => { + fileTransferHook(false); + return client.onWrite(buf); + }; + emscriptenHack(hooked); }; diff --git a/etc/emscripten/web-template/index.html b/etc/emscripten/web-template/index.html index d5f1bec759..a9e9e992a2 100755 --- a/etc/emscripten/web-template/index.html +++ b/etc/emscripten/web-template/index.html @@ -3,72 +3,321 @@ - GAP in the browser + + GAP in your browser + + - + -

-

GAP in the browser

-

- A WebAssembly build of GAP - running entirely in your browser — useful for trying things out - without installing. Not all packages work, working memory is - capped, and performance is reduced compared to a native build. - For real work, install GAP from - www.gap-system.org. -

+ +
Loading GAP…
+ +
+ This page needs SharedArrayBuffer, which is only + available when the page is served with the headers + Cross-Origin-Opener-Policy: same-origin and + Cross-Origin-Embedder-Policy: require-corp. The + bundled service worker handles this on hosts where you can't set + headers (e.g. GitHub Pages) — its first activation needs a reload, + so if you see this message, try reloading once. For local hosting + use etc/emscripten/serve.py. +
+ +
+
+
+
+ + +
+
What is this? · Licensing

@@ -78,108 +327,49 @@

GAP in the browser

WebAssembly build, served as a static site and run inside a Web Worker; you interact with it through an xterm-pty - terminal in the page below. + terminal.

To get started, try 1+1;, - Factorial(20);, or SymmetricGroup(5);. - The full GAP - manuals apply, with two caveats: some packages won't load - (anything that needs a native compiler or system library), and - anything that wants the local filesystem won't work. + Factorial(20);, or SymmetricGroup(5); — + or use the examples menu. The full + GAP manuals apply, + with some caveats: some packages won't load (anything that needs + a native compiler or system library), working memory is capped, + performance is reduced compared to a native build, and a running + computation cannot be interrupted — the Restart button is the + only way out of a loop.

Files downloaded on first visit are cached in your browser's IndexedDB, so subsequent visits start much faster. Clear the - site data to reset the cache. + site data to reset the cache. Files you create in a session are + not kept across reloads or restarts beyond the panel's + download cache.

GAP is free software, distributed under the GNU General Public License (version 2 or later). See the copyright notice for - the full statement. + the full statement. The Ubuntu fonts are distributed under the + Ubuntu Font Licence.

-
- Loading GAP… The first visit downloads several tens of megabytes; - subsequent visits are cached in your browser and load much faster. -
- -
- This page needs SharedArrayBuffer, which is only - available when the page is served with the headers - Cross-Origin-Opener-Policy: same-origin and - Cross-Origin-Embedder-Policy: require-corp. The - bundled service worker handles this on hosts where you can't set - headers (e.g. GitHub Pages); for local hosting use - etc/emscripten/serve.py. -
- -
-
-
- -