diff --git a/grp/classic.gi b/grp/classic.gi index 1298a58a50..d6c3b6c614 100644 --- a/grp/classic.gi +++ b/grp/classic.gi @@ -82,6 +82,8 @@ InstallMethod( SymplecticGroupCons, g := GroupWithGenerators( [ mat1, mat2 ] ); SetName( g, Concatenation("Sp(",String(d),",",String(q),")") ); SetDimensionOfMatrixGroup( g, d ); + + # 'mat1' contains a primitive root of 'f'. SetFieldOfMatrixGroup( g, f ); # add the size @@ -101,7 +103,7 @@ InstallMethod( SymplecticGroupCons, c[d/2+i,d/2-i+1] := -o; od; SetInvariantBilinearForm( g, - rec( matrix:= ImmutableMatrix( f, c, true ) ) ); + rec( matrix:= ImmutableMatrix( f, c, true ), baseDomain:= f ) ); SetIsFullSubgroupGLorSLRespectingBilinearForm(g,true); SetIsSubgroupSL(g,true); @@ -200,6 +202,8 @@ InstallMethod( GeneralUnitaryGroupCons, g:= GroupWithGenerators( gens ); SetName( g, Concatenation("GU(",String(n),",",String(q),")") ); SetDimensionOfMatrixGroup( g, n ); + + # 'mat1' contains a primitive root of 'f'. SetFieldOfMatrixGroup( g, f ); # Add the size. @@ -216,7 +220,7 @@ InstallMethod( GeneralUnitaryGroupCons, # construct the form c := Reversed( One( g ) ); SetInvariantSesquilinearForm( g, - rec( matrix:= ImmutableMatrix( f, c, true ) ) ); + rec( matrix:= ImmutableMatrix( f, c, true ), baseDomain:= f ) ); SetIsFullSubgroupGLorSLRespectingSesquilinearForm(g,true); # Return the group. @@ -313,7 +317,13 @@ InstallMethod( SpecialUnitaryGroupCons, g:= GroupWithGenerators( gens ); SetName( g, Concatenation("SU(",String(n),",",String(q),")") ); SetDimensionOfMatrixGroup( g, n ); - SetFieldOfMatrixGroup( g, f ); + if n <= 2 then + # The entries of 'gens' may generate a smaller field than 'f'. + SetFieldOfMatrixGroup( g, FieldOfMatrixList( gens ) ); + else + # 'mat1' contains a primitive root of 'f'. + SetFieldOfMatrixGroup( g, f ); + fi; # Add the size. size := 1; @@ -329,7 +339,7 @@ InstallMethod( SpecialUnitaryGroupCons, # construct the form c := Reversed( One( g ) ); SetInvariantSesquilinearForm( g, - rec( matrix:= ImmutableMatrix( f, c, true ) ) ); + rec( matrix:= ImmutableMatrix( f, c, true ), baseDomain:= f ) ); SetIsFullSubgroupGLorSLRespectingSesquilinearForm(g,true); SetIsSubgroupSL(g,true); @@ -340,15 +350,22 @@ InstallMethod( SpecialUnitaryGroupCons, ############################################################################# ## -#M SetInvariantQuadraticFormFromMatrix( , ) +#M SetInvariantQuadraticFormFromMatrix( , , ) ## -## Set the invariant quadratic form of to the matrix , and also -## set the bilinear form to the value required by the documentation, i.e., -# to + ^T. +## Set the invariant quadratic form of to the matrix . +## Also set the bilinear form to the value required by the documentation, +## i.e., to + ^T. +## In both forms, set the 'baseDomain' component. ## -BindGlobal( "SetInvariantQuadraticFormFromMatrix", function( g, mat ) - SetInvariantQuadraticForm( g, rec( matrix:= mat ) ); - SetInvariantBilinearForm( g, rec( matrix:= mat+TransposedMat(mat) ) ); +BindGlobal( "SetInvariantQuadraticFormFromMatrix", function( g, mat, F... ) + if Length( F ) <> 1 then + # In earlier versions of GAP, no 'baseDomain' was stored. + Error( "only the three argument variant of ", + "SetInvariantQuadraticFormFromMatrix is supported" ); + fi; + SetInvariantQuadraticForm( g, rec( matrix:= mat, baseDomain:= F[1] ) ); + SetInvariantBilinearForm( g, rec( matrix:= mat+TransposedMat(mat), + baseDomain:= F[1] ) ); end ); @@ -392,6 +409,8 @@ BindGlobal( "Oplus45", function() g:=List(g,i->ImmutableMatrix(f,i)); g := GroupWithGenerators( g ); SetDimensionOfMatrixGroup( g, 4 ); + + # 'f' is a prime field. SetFieldOfMatrixGroup( g, f ); # set the size @@ -399,7 +418,7 @@ BindGlobal( "Oplus45", function() # construct the forms SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, - [[0,1,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,1]] * One( f ), true ) ); + [[0,1,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,1]] * One( f ), true ), f ); # and return return g; @@ -451,6 +470,8 @@ BindGlobal( "Opm3", function( s, d ) g:=List(g,i->ImmutableMatrix(f,i,true)); g := GroupWithGenerators( g ); SetDimensionOfMatrixGroup( g, d ); + + # 'f' is a prime field. SetFieldOfMatrixGroup( g, f ); # construct the forms @@ -458,7 +479,7 @@ BindGlobal( "Opm3", function( s, d ) delta{[1,2]}{[1,2]} := [[0,1],[0,0]]*One( f ); delta[3,3] := One( f )*2; delta := ImmutableMatrix( f, delta, true ); - SetInvariantQuadraticFormFromMatrix( g, delta ); + SetInvariantQuadraticFormFromMatrix( g, delta, f ); # set the size delta := 1; @@ -519,6 +540,8 @@ BindGlobal( "OpmSmall", function( s, d, q ) g:=List(g,i->ImmutableMatrix(f,i,true)); g := GroupWithGenerators( g ); SetDimensionOfMatrixGroup( g, d ); + + # 'f' is a prime field. SetFieldOfMatrixGroup( g, f ); # construct the forms @@ -526,7 +549,7 @@ BindGlobal( "OpmSmall", function( s, d, q ) delta{[1,2]}{[1,2]} := [[0,1],[0,0]]*One( f ); delta[3,3] := One( f ); delta := ImmutableMatrix( f, delta, true ); - SetInvariantQuadraticFormFromMatrix( g, delta ); + SetInvariantQuadraticFormFromMatrix( g, delta, f ); # set the size delta := 1; @@ -588,7 +611,7 @@ BindGlobal( "OpmOdd", function( s, d, q ) [[1,0,0,0],[0,1,2,1],[2,0,2,0],[1,0,0,1]]*One( f ), [[0,2,2,2],[0,1,1,2],[1,0,2,0],[1,2,2,0]]*One( f ) ] ); SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, - [[0,1,0,0],[0,0,0,0],[0,0,2,0],[0,0,0,1]]*One( f ), true ) ); + [[0,1,0,0],[0,0,0,0],[0,0,2,0],[0,0,0,1]]*One( f ), true ), f ); SetSize( g, 1152 ); return g; elif q = 3 and d = 4 and s = -1 then @@ -596,7 +619,7 @@ BindGlobal( "OpmOdd", function( s, d, q ) [[0,2,0,0],[2,1,0,1],[0,2,0,1],[0,0,1,0]]*One( f ), [[2,0,0,0],[1,2,0,2],[1,0,0,1],[0,0,1,0]]*One( f ) ] ); SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, - [[0,1,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,1]]*One( f ), true ) ); + [[0,1,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,1]]*One( f ), true ), f ); SetSize( g, 1440 ); return g; elif q = 5 and d = 4 and s = +1 then @@ -652,6 +675,8 @@ BindGlobal( "OpmOdd", function( s, d, q ) g:=List(g,i->ImmutableMatrix(f,i,true)); g := GroupWithGenerators( g ); SetDimensionOfMatrixGroup( g, d ); + + # 'phi' contains a primitive root of 'f'. SetFieldOfMatrixGroup( g, f ); # construct the forms @@ -659,7 +684,7 @@ BindGlobal( "OpmOdd", function( s, d, q ) delta{[1,2]}{[1,2]} := [[0,1],[0,0]]*One( f ); delta[3,3] := beta; delta := ImmutableMatrix( f, delta, true ); - SetInvariantQuadraticFormFromMatrix( g, delta ); + SetInvariantQuadraticFormFromMatrix( g, delta, f ); # set the size delta := 1; @@ -697,7 +722,7 @@ BindGlobal( "Oplus2", function( q ) # construct the group, set the order, and return g := GroupWithGenerators( [ m1, m2 ] ); SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, - [ [ 0, 1 ], [ 0, 0 ] ] * z^0, true ) ); + [ [ 0, 1 ], [ 0, 0 ] ] * z^0, true ), f ); SetSize( g, 2*(q-1) ); return g; end ); @@ -737,6 +762,8 @@ BindGlobal( "Oplus4Even", function( q ) g:=List(g,i->ImmutableMatrix(f,i,true)); g := GroupWithGenerators( g ); SetDimensionOfMatrixGroup( g, 4 ); + + # 'phi*rho' contains a primitive root of 'f'. SetFieldOfMatrixGroup( g, f ); # set the size @@ -744,7 +771,7 @@ BindGlobal( "Oplus4Even", function( q ) # construct the forms SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, - [[0,1,0,0],[0,0,0,0],[0,0,0,1],[0,0,0,0]] * One( f ), true ) ); + [[0,1,0,0],[0,0,0,0],[0,0,0,1],[0,0,0,0]] * One( f ), true ), f ); # and return return g; @@ -847,6 +874,8 @@ BindGlobal( "OplusEven", function( d, q ) g:=List(g,i->ImmutableMatrix(f,i,true)); g := GroupWithGenerators( g ); SetDimensionOfMatrixGroup( g, d ); + + # 'phi*delta2' contains a primitive root of 'f'. SetFieldOfMatrixGroup( g, f ); # construct the forms @@ -854,7 +883,7 @@ BindGlobal( "OplusEven", function( d, q ) for i in [ 1 .. d/2 ] do delta[2*i-1,2*i] := One( f ); od; - SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, delta, true ) ); + SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, delta, true ), f ); # set the size delta := 1; @@ -914,7 +943,7 @@ BindGlobal( "Ominus2", function( q ) m2:=ImmutableMatrix(GF(q),m2,true); g := GroupWithGenerators( [ m1, m2 ] ); SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, - [ [ 1, 1 ], [ 0, t ] ] * one, true ) ); + [ [ 1, 1 ], [ 0, t ] ] * one, true ), f ); SetSize( g, 2*(q+1) ); return g; @@ -965,6 +994,8 @@ BindGlobal( "Ominus4Even", function( q ) g:=List(g,i->ImmutableMatrix(f,i,true)); g := GroupWithGenerators( g ); SetDimensionOfMatrixGroup( g, 4 ); + + # 'phi*rho' contains a primitive root of 'f'. SetFieldOfMatrixGroup( g, f ); # set the size @@ -972,7 +1003,7 @@ BindGlobal( "Ominus4Even", function( q ) # construct the forms SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, - [[0,1,0,0],[0,0,0,0],[0,0,t,1],[0,0,0,t]] * One( f ), true ) ); + [[0,1,0,0],[0,0,0,0],[0,0,t,1],[0,0,0,t]] * One( f ), true ), f ); # and return return g; @@ -1083,6 +1114,8 @@ BindGlobal( "OminusEven", function( d, q ) g:=List(g,i->ImmutableMatrix(f,i,true)); g := GroupWithGenerators( g ); SetDimensionOfMatrixGroup( g, d ); + + # 'phi*delta2' contains a primitive root of 'f'. SetFieldOfMatrixGroup( g, f ); # construct the forms @@ -1092,7 +1125,7 @@ BindGlobal( "OminusEven", function( d, q ) od; delta[3,3] := t; delta[4,4] := t; - SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, delta, true ) ); + SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, delta, true ), f ); # set the size delta := 1; @@ -1131,9 +1164,9 @@ BindGlobal( "OzeroOdd", function( d, q, b ) s:= ImmutableMatrix( f, [ [ One( f ) ] ], true ); g:= GroupWithGenerators( [ -s ] ); SetDimensionOfMatrixGroup( g, d ); - SetFieldOfMatrixGroup( g, f ); + SetFieldOfMatrixGroup( g, PrimeField( f ) ); SetSize( g, 2 ); - SetInvariantQuadraticFormFromMatrix( g, s ); + SetInvariantQuadraticFormFromMatrix( g, s, f ); return g; fi; @@ -1164,6 +1197,8 @@ BindGlobal( "OzeroOdd", function( d, q, b ) g:=List(g,i->ImmutableMatrix(f,i,true)); g := GroupWithGenerators( g ); SetDimensionOfMatrixGroup( g, d ); + + # 'phi' contains a primitive root of 'f'. SetFieldOfMatrixGroup( g, f ); # and set its size @@ -1179,7 +1214,7 @@ BindGlobal( "OzeroOdd", function( d, q, b ) # construct the forms s := b * IdentityMat( d, f ); s{[1,2]}{[1,2]} := [[0,1],[0,0]]*One( f ); - SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, s, true ) ); + SetInvariantQuadraticFormFromMatrix( g, ImmutableMatrix( f, s, true ), f ); # and return return g; @@ -1232,9 +1267,9 @@ BindGlobal( "OzeroEven", function( d, q ) s:= ImmutableMatrix( f, [ [ o ] ], true ); g:= GroupWithGenerators( [], s ); SetDimensionOfMatrixGroup( g, d ); - SetFieldOfMatrixGroup( g, f ); + SetFieldOfMatrixGroup( g, PrimeField( f ) ); SetSize( g, 1 ); - SetInvariantQuadraticFormFromMatrix( g, s ); + SetInvariantQuadraticFormFromMatrix( g, s, f ); return g; elif d = 3 then @@ -1290,6 +1325,8 @@ BindGlobal( "OzeroEven", function( d, q ) # avoid to call 'Group' because this would check invertibility ... g:= GroupWithGenerators( [ mat1, mat2 ] ); SetDimensionOfMatrixGroup( g, d ); + + # 'mat1' contains a primitive root of 'f'. SetFieldOfMatrixGroup( g, f ); SetIsSubgroupSL( g, true ); @@ -1309,7 +1346,7 @@ BindGlobal( "OzeroEven", function( d, q ) s[(d-1)/2+i,i]:= o; od; s:= ImmutableMatrix( f, s, true ); - SetInvariantQuadraticFormFromMatrix( g, s ); + SetInvariantQuadraticFormFromMatrix( g, s, f ); # and return return g; @@ -1437,7 +1474,7 @@ InstallMethod( SpecialOrthogonalGroupCons, IsPosInt, IsPosInt ], function( filter, e, d, q ) - local G, gens, U, i; + local G, gens, U, i, F, form; G:= GeneralOrthogonalGroupCons( filter, e, d, q ); if q mod 2 = 1 then @@ -1465,8 +1502,13 @@ InstallMethod( SpecialOrthogonalGroupCons, String(q), ")" ) ); # Set the invariant quadratic form and the symmetric bilinear form. - SetInvariantBilinearForm( U, InvariantBilinearForm( G ) ); - SetInvariantQuadraticForm( U, InvariantQuadraticForm( G ) ); + F:= GF(q); + form:= InvariantBilinearForm( G ); + SetInvariantBilinearForm( U, rec( matrix:= form.matrix, + baseDomain:= F ) ); + form:= InvariantQuadraticForm( G ); + SetInvariantQuadraticForm( U, rec( matrix:= form.matrix, + baseDomain:= F ) ); SetIsFullSubgroupGLorSLRespectingQuadraticForm( U, true ); SetIsFullSubgroupGLorSLRespectingBilinearForm( U, true ); G:= U; @@ -1570,6 +1612,8 @@ BindGlobal( "OmegaZero", function( d, q ) g:= List( g, i -> ImmutableMatrix( f, i, true ) ); g:= GroupWithGenerators( g ); SetDimensionOfMatrixGroup( g, d ); + + # One of the generators contains a primitive root of 'f' or its square. SetFieldOfMatrixGroup( g, f ); # and set its size @@ -1591,7 +1635,7 @@ BindGlobal( "OmegaZero", function( d, q ) x[i,d-i+1] := o; od; x[m+1,m+1] := (Characteristic(f)+1)/4*o; - SetInvariantQuadraticFormFromMatrix(g, ImmutableMatrix( f, x, true ) ); + SetInvariantQuadraticFormFromMatrix(g, ImmutableMatrix( f, x, true ), f ); # and return return g; @@ -1683,6 +1727,11 @@ BindGlobal( "OmegaPlus", function( d, q ) g:= List( g, i -> ImmutableMatrix( f, i, true ) ); g:= GroupWithGenerators( g ); SetDimensionOfMatrixGroup( g, d ); + + # - If 'd = 4' then 'z:= Z(q^2)^(q-1)' generates the field 'GF(q^2)', + # and 'z + z^q' generates the field 'GF(q)' + # because 'z' is a root of 'x^2 - (z + z^q) * x + 1'. + # - If 'd <> 4' then the first generator contains a primitive root of 'f'. SetFieldOfMatrixGroup( g, f ); # and set its size @@ -1704,7 +1753,7 @@ BindGlobal( "OmegaPlus", function( d, q ) x[i,d-i+1] := o; od; x:= ImmutableMatrix( f, x, true ); - SetInvariantQuadraticFormFromMatrix( g, x ); + SetInvariantQuadraticFormFromMatrix( g, x, f ); # and return return g; @@ -1717,7 +1766,9 @@ BindGlobal( "OmegaPlus", function( d, q ) ## BindGlobal( "OmegaMinus", function( d, q ) local f, o, m, xi, mo, nu, nubar, nutrace, nuinvtrace, nunorm, h, x, n, - i, g, s, q2, q2i; + i, g, s, q2, q2i, form; + + f:= GF(q); # must be even if d mod 2 = 1 then @@ -1739,11 +1790,16 @@ BindGlobal( "OmegaMinus", function( d, q ) # and 'Omega(-1,2,q)' is its unique subgroup of index two. s:= GroupWithGenerators( [ h^2 ] ); fi; - SetInvariantBilinearForm( s, InvariantBilinearForm( g ) ); - SetInvariantQuadraticForm( s, InvariantQuadraticForm( g ) ); + form:= InvariantBilinearForm( g ); + SetInvariantBilinearForm( s, rec( matrix:= form.matrix, + baseDomain:= f ) ); + form:= InvariantQuadraticForm( g ); + SetInvariantQuadraticForm( s, rec( matrix:= form.matrix, + baseDomain:= f ) ); + # We do not call 'SetFieldOfMatrixGroup'. return s; fi; - f:= GF(q); + o:= One( f ); m:= d / 2 - 1; xi:= Z(q); @@ -1794,6 +1850,10 @@ BindGlobal( "OmegaMinus", function( d, q ) g:= List( g, i -> ImmutableMatrix( f, i, true ) ); g:= GroupWithGenerators( g ); SetDimensionOfMatrixGroup( g, d ); + + # 'h' contains the entries '-nutrace' and 'nunorm', + # at most one of them can lie in a proper subfield of 'f' + # because 'nu' is a root of 'x^2 - nutrace * x + nunorm'. SetFieldOfMatrixGroup( g, f ); # and set its size @@ -1819,7 +1879,7 @@ BindGlobal( "OmegaMinus", function( d, q ) x[m,d-m] := -o; x[m+1,d-m+1] := -xi; x:= ImmutableMatrix( f, x, true ); - SetInvariantQuadraticFormFromMatrix( g, x ); + SetInvariantQuadraticFormFromMatrix( g, x, f ); # and return return g; diff --git a/grp/ree.gi b/grp/ree.gi index 3fa172b0d3..54b8f95a26 100644 --- a/grp/ree.gi +++ b/grp/ree.gi @@ -76,7 +76,7 @@ local theta, m, f, bas, one, zero, x, h, r, gens, G, i; G:=Group(gens,One(gens[1])); SetName(G,Concatenation("Ree(",String(q),")")); SetDimensionOfMatrixGroup(G,7); - SetFieldOfMatrixGroup(G,f); + SetFieldOfMatrixGroup(G,f); # 'h(PrimitiveRoot(f))' contains a prim. root SetIsFinite(G,true); SetSize(G,q^3*(q-1)*(q^3+1)); SetIsSimpleGroup(G, q > 3); diff --git a/grp/suzuki.gi b/grp/suzuki.gi index 2e8f255bac..f6cb194086 100644 --- a/grp/suzuki.gi +++ b/grp/suzuki.gi @@ -52,7 +52,7 @@ function ( filter, q ) SetName(G,Concatenation("Sz(",String(q),")")); SetDimensionOfMatrixGroup(G,4); - SetFieldOfMatrixGroup(G,f); + SetFieldOfMatrixGroup(G,f); # the first generator contains a prim. root SetIsFinite(G,true); SetSize(G,q^2*(q-1)*(q^2+1)); SetIsSimpleGroup(G, q > 2); diff --git a/lib/grpffmat.gi b/lib/grpffmat.gi index 49aa289ed2..147563c60b 100644 --- a/lib/grpffmat.gi +++ b/lib/grpffmat.gi @@ -701,47 +701,24 @@ end ); ############################################################################# ## -#M NrConjugacyClasses( ) . . . . . . . . . . . . . . Method for GU(n,q) +#M NrConjugacyClasses( ) . . . . . . . . Method for GU(n,q) and SU(n,q) ## InstallMethod( NrConjugacyClasses, - "for GU(n,q)", - true, + "for GU(n,q) and SU(n,q)", [ IsFFEMatrixGroup and IsFinite and IsFullSubgroupGLorSLRespectingSesquilinearForm ], - 0, function ( G ) - local n,q; - if IsSubgroupSL(G) then TryNextMethod(); fi; - n := DimensionOfMatrixGroup(G); - q := RootInt(Size(FieldOfMatrixGroup(G))); + q := RootInt(Size(InvariantSesquilinearForm(G).baseDomain)); + if IsSubgroupSL(G) then + return NrConjugacyClassesSU(n,q); + fi; return NrConjugacyClassesGU(n,q); end ); -############################################################################# -## -#M NrConjugacyClasses( ) . . . . . . . . . . Method for natural SU(n,q) -## -InstallMethod( NrConjugacyClasses, - "for natural SU", - true, - [ IsFFEMatrixGroup and IsFinite - and IsFullSubgroupGLorSLRespectingSesquilinearForm - and IsSubgroupSL ], - 0, -function ( G ) - - local n,q; - - n := DimensionOfMatrixGroup(G); - q := RootInt(Size(FieldOfMatrixGroup(G))); - - return NrConjugacyClassesSU(n,q); -end ); - InstallGlobalFunction(ClassesProjectiveImage,function(act) local G,PG,cl,c,i,sel,p,z,a,x,prop,fus,f,reps,repi,repo,zel,fcl, diff --git a/lib/grpmat.gd b/lib/grpmat.gd index d2c9d0a906..8c9231140f 100644 --- a/lib/grpmat.gd +++ b/lib/grpmat.gd @@ -322,11 +322,20 @@ InstallTrueMethod(IsSubgroupSL,IsNaturalSL); ## ## ## -## This attribute describes a bilinear form that is invariant under the -## matrix group matgrp. -## The form is given by a record with the component matrix -## which is a matrix F such that for every generator g of -## matgrp the equation g \cdot F \cdot g^{tr} = F holds. +## For a matrix group matgrp, +## returns a record containing at least the components matrix, +## whose value is a matrix M, +## and baseDomain, whose value is a field. +##

+## This record describes a bilinear form that is invariant under +## matgrp. +## For every generator g of matgrp, +## the equation g \cdot M \cdot g^{tr} = M holds. +##

+## The attribute value is set for example in groups constructed with +## . +## Together with , +## it can be used for efficient membership tests in matgrp. ## ## ## <#/GAPDoc> @@ -343,11 +352,19 @@ DeclareAttribute( "InvariantBilinearForm", IsMatrixGroup ); ## ## ## -## This property tests, whether a matrix group matgrp is the full -## subgroup of GL or SL (the property determines -## which it is) in the right dimension over the (smallest) ring which -## contains all entries of its elements, respecting the form stored as the value of +## If this property is set then the matrix group matgrp is the full +## subgroup of GL(d, q) or SL(d, q) +## respecting the form stored as the value of ## for matgrp. +##

+## The value d is the value of +## matgrp, +## and q is the size of the baseDomain component of the +## record stored as . +##

+## The property of matgrp determines +## whether GL or SL is meant for +## . ## ## ## <#/GAPDoc> @@ -365,17 +382,25 @@ InstallTrueMethod( IsGroup, IsFullSubgroupGLorSLRespectingBilinearForm ); ## ## ## -## This attribute describes a sesquilinear form that is invariant under the -## matrix group matgrp over the field F with q^2 -## elements. -## The form is given by a record with the component matrix -## which is a matrix M such that for every generator g of -## matgrp +## For a matrix group matgrp, +## returns a record containing at least the components matrix, +## whose value is a matrix M, +## and baseDomain, whose value is a field F. +##

+## This record describes a sesquilinear form that is invariant under +## matgrp. +## For every generator g of matgrp, ## the equation g \cdot M \cdot (g^{tr})^f = M holds, -## where f is the automorphism of F that raises each element -## to its q-th power. +## where f is an automorphism of F. +## If F has q^2 elements then f raises each element +## of F to its q-th power. ## (f can be obtained as a power of the ## value of F.) +##

+## The attribute value is set for example in groups constructed with +## . Together with +## , +## it can be used for efficient membership tests in matgrp. ## ## ## <#/GAPDoc> @@ -392,10 +417,19 @@ DeclareAttribute( "InvariantSesquilinearForm", IsMatrixGroup ); ## ## ## -## This property tests, whether a matrix group matgrp is the full -## subgroup of GL or SL (the property determines -## which it is) respecting the form stored as the value of +## If this property is set then the matrix group matgrp is the full +## subgroup of GL(d, q) or SL(d, q) +## respecting the form stored as the value of ## for matgrp. +##

+## The value d is the value of +## matgrp, +## and q is the size of the baseDomain component of the +## record stored as . +##

+## The property of matgrp determines +## whether GL or SL is meant for +## . ## ## ## <#/GAPDoc> @@ -415,36 +449,41 @@ InstallTrueMethod( IsGroup, IsFullSubgroupGLorSLRespectingSesquilinearForm ); ## ## ## For a matrix group matgrp, -## returns a record containing at least the component matrix -## whose value is a matrix Q. -## The quadratic form q on the natural vector space V on which -## matgrp acts is given by q(v) = v Q v^{tr}, +## returns a record containing at least the components matrix, +## whose value is a matrix Q, +## and baseDomain, whose value is a field F. +##

+## The quadratic form q on the natural F-vector space V +## on which matgrp acts is given by q(v) = v Q v^{tr}, ## and the invariance under matgrp is given by the equation ## q(v) = q(v M) for all v \in V and M in ## matgrp. ## (Note that the invariance of q does not imply that the ## matrix Q is invariant under matgrp.) ##

-## q is defined relative to an invariant symmetric bilinear form -## f (see ), +## The function q is defined relative to an invariant symmetric +## bilinear form b (see ), ## via the equation ## q(\lambda x + \mu y) = -## \lambda^2 q(x) + \lambda \mu f(x,y) + \mu^2 q(y), +## \lambda^2 q(x) + \lambda \mu b(x,y) + \mu^2 q(y), ## see . -## If f is represented by the matrix F then this implies -## F = Q + Q^{tr}. -## In characteristic different from 2, we have q(x) = f(x,x)/2, +## If b is represented by the matrix B then this implies +## B = Q + Q^{tr}. +## In characteristic different from 2, we have q(x) = b(x,x)/2, ## so Q can be chosen as the strictly upper triangular part of -## F plus half of the diagonal part of F. -## In characteristic 2, F does not determine Q +## B plus half of the diagonal part of B. +## In characteristic 2, B does not determine Q ## but still Q can be chosen as an upper (or lower) triangular matrix. ##

## Whenever the value is set in a ## matrix group then also the value ## can be accessed, ## and the two values are compatible in the above sense. -## -## +##

+## The attribute value is set for example in groups constructed with +## . Together with +## , +## it can be used for efficient membership tests in matgrp. ## ## ## <#/GAPDoc> @@ -461,35 +500,45 @@ DeclareAttribute( "InvariantQuadraticForm", IsMatrixGroup ); ## ## ## -## This property tests, whether the matrix group matgrp is the full -## subgroup of GL or SL (the property determines -## which it is) in the right dimension over the (smallest) ring which -## contains all entries of its elements, -## respecting the value -## of matgrp. +## If this property is set then the matrix group matgrp is the full +## subgroup of GL(d, q) or SL(d, q) +## respecting the form stored as the value of +## for matgrp. +##

+## The value d is the value of +## matgrp, +## and q is the size of the baseDomain component of the +## record stored as . +##

+## The property of matgrp determines +## whether GL or SL is meant for +## . +##

## g:= Sp( 2, 3 );; ## gap> m:= InvariantBilinearForm( g ).matrix; ## [ [ 0*Z(3), Z(3)^0 ], [ Z(3), 0*Z(3) ] ] -## gap> [ 0, 1 ] * m * [ 1, -1 ]; # evaluate the bilinear form +## gap> [ 0, 1 ] * m * [ 1, -1 ]; # evaluate the bilinear form ## Z(3) ## gap> IsFullSubgroupGLorSLRespectingBilinearForm( g ); ## true ## gap> g:= SU( 2, 4 );; ## gap> m:= InvariantSesquilinearForm( g ).matrix; ## [ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, 0*Z(2) ] ] -## gap> [ 0, 1 ] * m * [ 1, 1 ]; # evaluate the bilinear form +## gap> [ 0, 1 ] * m * [ 1, 1 ]; # evaluate the sesquilinear form ## Z(2)^0 ## gap> IsFullSubgroupGLorSLRespectingSesquilinearForm( g ); ## true +## gap> IsSubgroupSL( g ); +## true ## gap> g:= GO( 1, 2, 3 );; ## gap> m:= InvariantBilinearForm( g ).matrix; ## [ [ 0*Z(3), Z(3)^0 ], [ Z(3)^0, 0*Z(3) ] ] -## gap> [ 0, 1 ] * m * [ 1, 1 ]; # evaluate the bilinear form +## gap> [ 0, 1 ] * m * [ 1, 1 ]; # evaluate the bilinear form ## Z(3)^0 ## gap> q:= InvariantQuadraticForm( g ).matrix; ## [ [ 0*Z(3), Z(3)^0 ], [ 0*Z(3), 0*Z(3) ] ] -## gap> [ 0, 1 ] * q * [ 0, 1 ]; # evaluate the quadratic form +## gap> [ 0, 1 ] * q * [ 0, 1 ]; # evaluate the quadratic form ## 0*Z(3) ## gap> IsFullSubgroupGLorSLRespectingQuadraticForm( g ); ## true diff --git a/lib/grpmat.gi b/lib/grpmat.gi index 9c00e8c1b7..1ef97e1639 100644 --- a/lib/grpmat.gi +++ b/lib/grpmat.gi @@ -846,6 +846,7 @@ InstallMethod( \in, "respecting quadratic form", IsElmsColls, # bilinear form, which is cheaper to check, # thus we install the current method first function( mat, G ) + # We may use `FieldOfMatrixGroup( G )` instead of `baseDomain` of the form. return IsSubset( FieldOfMatrixGroup( G ), FieldOfMatrixList( [ mat ] ) ) and ( not IsSubgroupSL( G ) or IsOne( DeterminantMat( mat ) ) ) and RespectsQuadraticForm( InvariantQuadraticForm( G ).matrix, mat ); @@ -856,6 +857,7 @@ InstallMethod( \in, "respecting bilinear form", IsElmsColls, {} -> RankFilter( IsHandledByNiceMonomorphism ), # override nice mon. method function( mat, G ) local inv; + # We may use `FieldOfMatrixGroup( G )` instead of `baseDomain` of the form. if not IsSubset( FieldOfMatrixGroup( G ), FieldOfMatrixList( [ mat ] ) ) or ( IsSubgroupSL( G ) and not IsOne( DeterminantMat( mat ) ) ) then return false; @@ -868,13 +870,15 @@ InstallMethod( \in, "respecting sesquilinear form", IsElmsColls, [ IsMatrix, IsFullSubgroupGLorSLRespectingSesquilinearForm ], {} -> RankFilter( IsHandledByNiceMonomorphism ), # override nice mon. method function( mat, G ) - local pow, inv; + local form, pow, inv; + # We may use `FieldOfMatrixGroup( G )` instead of `baseDomain` of the form. if not IsSubset( FieldOfMatrixGroup( G ), FieldOfMatrixList( [ mat ] ) ) or ( IsSubgroupSL( G ) and not IsOne( DeterminantMat( mat ) ) ) then return false; fi; - pow:= RootInt( Size( FieldOfMatrixGroup( G ) ) ); - inv:= InvariantSesquilinearForm(G).matrix; + form:= InvariantSesquilinearForm(G); + pow:= RootInt( Size( form.baseDomain ) ); + inv:= form.matrix; return mat * inv * List( TransposedMat( mat ), row -> List( row, x -> x^pow ) ) = inv; @@ -1274,7 +1278,7 @@ InstallMethod( InvariantBilinearForm, InstallMethod( ConjugateGroup, ", ", IsCollsElms, [ IsMatrixGroup, IsMultiplicativeElementWithInverse ], function( G, g ) - local H, m, ginv, nice, conj; + local H, F, form, m, D, ginv, pow, nice, conj; H := GroupByGenerators( OnTuples( GeneratorsOfGroup( G ), g ), One( G ) ); UseIsomorphismRelation( G, H ); @@ -1287,27 +1291,45 @@ InstallMethod( ConjugateGroup, ", ", IsCollsElms, if HasIsSubgroupSL( G ) then SetIsSubgroupSL( H, IsSubgroupSL( G ) ); fi; + F:= FieldOfMatrixList( [ g ] ); if HasInvariantBilinearForm( G ) then if not IsBound( ginv ) then ginv := g^-1; fi; - m := ginv * InvariantBilinearForm( G ).matrix * TransposedMat( ginv ); - SetInvariantBilinearForm( H, rec( matrix := m ) ); + form := InvariantBilinearForm( G ); + m := ginv * form.matrix * TransposedMat( ginv ); + if not IsBound( D ) then + D:= form.baseDomain; + if not IsSubset( D, F ) then + D:= ClosureField( D, F ); + fi; + fi; + SetInvariantBilinearForm( H, rec( matrix := m, baseDomain := D ) ); fi; if HasInvariantQuadraticForm( G ) then if not IsBound( ginv ) then ginv := g^-1; fi; - m := ginv * InvariantQuadraticForm( G ).matrix * TransposedMat( ginv ); - SetInvariantQuadraticForm( H, rec( matrix := m ) ); + form := InvariantQuadraticForm( G ); + m := ginv * form.matrix * TransposedMat( ginv ); + if not IsBound( D ) then + D:= form.baseDomain; + if not IsSubset( D, F ) then + D:= ClosureField( D, F ); + fi; + fi; + SetInvariantQuadraticForm( H, rec( matrix := m, baseDomain := D ) ); fi; - if IsSubset( FieldOfMatrixGroup( G ), FieldOfMatrixList( [ g ] ) ) then + if IsSubset( FieldOfMatrixGroup( G ), F ) then if HasIsNaturalGL( G ) then SetIsNaturalGL( H, IsNaturalGL( G ) ); fi; if HasIsNaturalSL( G ) then SetIsNaturalSL( H, IsNaturalSL( G ) ); fi; + + # We have in particular that the 'baseDomain' of a stored invariant form + # contains 'F'. if HasIsFullSubgroupGLorSLRespectingBilinearForm( G ) and IsFullSubgroupGLorSLRespectingBilinearForm( G ) then SetIsFullSubgroupGLorSLRespectingBilinearForm( H, true ); @@ -1316,6 +1338,22 @@ InstallMethod( ConjugateGroup, ", ", IsCollsElms, and IsFullSubgroupGLorSLRespectingQuadraticForm( G ) then SetIsFullSubgroupGLorSLRespectingQuadraticForm( H, true ); fi; + + # For a stored sesquilinear form, we have to keep the meaning + # of the involutory field automorphism, + # which is defined by the 'baseDomain' component of the form. + # We transfer the form only if the field of definition does not grow. + if HasInvariantSesquilinearForm( G ) then + if not IsBound( ginv ) then + ginv:= g^-1; + fi; + form:= InvariantSesquilinearForm( G ); + D:= form.baseDomain; + pow:= RootInt( Size( D ) ); + m:= ginv * form.matrix * List( TransposedMat( ginv ), + row -> List( row, x -> x^pow ) ); + SetInvariantSesquilinearForm( H, rec( matrix:= m, baseDomain:= D ) ); + fi; fi; if HasNiceMonomorphism( G ) then nice := NiceMonomorphism( G ); diff --git a/tst/testinstall/grp/classic-forms.tst b/tst/testinstall/grp/classic-forms.tst index 908e0693c4..94339ef7a8 100644 --- a/tst/testinstall/grp/classic-forms.tst +++ b/tst/testinstall/grp/classic-forms.tst @@ -1,3 +1,10 @@ +#@local CheckGeneratorsInvertible, CheckGeneratorsSpecial, CheckField +#@local CheckBilinearForm, CheckQuadraticForm, frob, CheckSesquilinearForm +#@local CheckSize, CheckClasses, CheckMembershipFromForm +#@local CheckMembershipBilinear, CheckMembershipBilinear2 +#@local CheckMembershipSesquilinear +#@local CheckMembershipQuadratic, CheckMembershipQuadratic2 +#@local grps1, grps2, grps, d, q, G, m # # Tests invariant forms of classic groups # @@ -13,6 +20,12 @@ gap> CheckGeneratorsSpecial := function(G) > g -> IsOne(Determinant(g))); > end;; +# verify `FieldOfMatrixGroup` +gap> CheckField := function(G) +> return FieldOfMatrixGroup( G ) +> = FieldOfMatrixGroup( Group( GeneratorsOfGroup( G ), One( G ) ) ); +> end;; + # verify that forms are given and preserved gap> CheckBilinearForm := function(G) > local M; @@ -34,7 +47,7 @@ gap> frob := function(g,aut) gap> CheckSesquilinearForm := function(G) > local M, F, aut; > M := InvariantSesquilinearForm(G).matrix; -> F := FieldOfMatrixGroup(G); +> F := InvariantSesquilinearForm(G).baseDomain; > aut := FrobeniusAutomorphism(F); > aut := aut^(DegreeOverPrimeField(F)/2); > return ForAll(GeneratorsOfGroup(G), @@ -44,88 +57,167 @@ gap> CheckSesquilinearForm := function(G) # verify group size if the underlying module is small gap> CheckSize := function(g) > if Size(FieldOfMatrixGroup(g))^DimensionOfMatrixGroup(g) < 1000 then -> return Size(g) = Size(Group(GeneratorsOfGroup(g))); +> return Size(g) = Size(Group(GeneratorsOfGroup(g), One(g))); +> fi; +> return true; +> end;; + +# verify class numbers if the group is small +gap> CheckClasses:= function( G ) +> if Size(FieldOfMatrixGroup(G))^DimensionOfMatrixGroup(G) < 1000 then +> return NrConjugacyClasses(G) +> = NrConjugacyClasses(Group(GeneratorsOfGroup(G), One(G))); +> fi; +> return true; +> end;; + +# run some membership tests (there are special methods based on forms) +gap> CheckMembershipFromForm:= function( G, form ) +> local full; +> full:= GL( DimensionOfMatrixGroup( G ), form.baseDomain ); +> return ForAll( [ 1 .. 10 ], i -> PseudoRandom( G ) in G ) and +> ( ForAny( GeneratorsOfGroup( full ), g -> not ( g in G ) ) or +> Size( G ) = Size( full ) ); +> end;; +gap> CheckMembershipBilinear:= function( G ) +> return HasIsFullSubgroupGLorSLRespectingBilinearForm( G ) +> and IsFullSubgroupGLorSLRespectingBilinearForm( G ) +> and CheckMembershipFromForm( G, InvariantBilinearForm( G ) ); +> end;; +gap> CheckMembershipBilinear2:= function( G ) +> if HasIsFullSubgroupGLorSLRespectingBilinearForm( G ) +> and IsFullSubgroupGLorSLRespectingBilinearForm( G ) then +> return CheckMembershipFromForm( G, InvariantBilinearForm( G ) ); +> fi; +> return true; +> end;; +gap> CheckMembershipSesquilinear:= function( G ) +> return HasIsFullSubgroupGLorSLRespectingSesquilinearForm( G ) +> and IsFullSubgroupGLorSLRespectingSesquilinearForm( G ) +> and CheckMembershipFromForm( G, InvariantSesquilinearForm( G ) ); +> end;; +gap> CheckMembershipQuadratic:= function( G ) +> return HasIsFullSubgroupGLorSLRespectingQuadraticForm( G ) +> and IsFullSubgroupGLorSLRespectingQuadraticForm( G ) +> and CheckMembershipFromForm( G, InvariantQuadraticForm( G ) ); +> end;; +gap> CheckMembershipQuadratic2:= function( G ) +> if HasIsFullSubgroupGLorSLRespectingQuadraticForm( G ) +> and IsFullSubgroupGLorSLRespectingQuadraticForm( G ) then +> return CheckMembershipFromForm( G, InvariantQuadraticForm( G ) ); > fi; > return true; > end;; # odd-dimensional general orthogonal groups -gap> grps:=[];; -gap> for d in [3,5,7] do +gap> grps1:=[];; +gap> grps2:=[];; +gap> for d in [1,3,5,7] do > for q in [2,3,4,5,7,8,9,16,17,25,27] do -> Add(grps, GO(d,q)); -> Add(grps, GO(d,q) ^ RandomInvertibleMat(d,GF(q))); -> Add(grps, GO(d,q) ^ RandomInvertibleMat(d,GF(q^2))); +> Add(grps1, GO(d,q)); +> Add(grps2, GO(d,q) ^ RandomInvertibleMat(d,GF(q))); +> Add(grps2, GO(d,q) ^ RandomInvertibleMat(d,GF(q^2))); > od; > od; +gap> grps:= Concatenation( grps1, grps2 );; gap> ForAll(grps, CheckGeneratorsInvertible); true +gap> ForAll(grps, CheckField); +true gap> ForAll(grps, CheckBilinearForm); true gap> ForAll(grps, CheckQuadraticForm); true gap> ForAll(grps, CheckSize); true +gap> ForAll(grps1, CheckMembershipQuadratic); +true +gap> ForAll(grps2, CheckMembershipQuadratic2); +true # even-dimensional general orthogonal groups -gap> grps:=[];; +gap> grps1:=[];; +gap> grps2:=[];; gap> for d in [2,4,6,8] do > for q in [2,3,4,5,7,8,9,16,17,25,27] do -> Add(grps, GO(+1,d,q)); -> Add(grps, GO(-1,d,q)); -> Add(grps, GO(+1,d,q) ^ RandomInvertibleMat(d,GF(q))); -> Add(grps, GO(-1,d,q) ^ RandomInvertibleMat(d,GF(q))); -> Add(grps, GO(+1,d,q) ^ RandomInvertibleMat(d,GF(q^2))); -> Add(grps, GO(-1,d,q) ^ RandomInvertibleMat(d,GF(q^2))); +> Add(grps1, GO(+1,d,q)); +> Add(grps1, GO(-1,d,q)); +> Add(grps2, GO(+1,d,q) ^ RandomInvertibleMat(d,GF(q))); +> Add(grps2, GO(-1,d,q) ^ RandomInvertibleMat(d,GF(q))); +> Add(grps2, GO(+1,d,q) ^ RandomInvertibleMat(d,GF(q^2))); +> Add(grps2, GO(-1,d,q) ^ RandomInvertibleMat(d,GF(q^2))); > od; > od; +gap> grps:= Concatenation( grps1, grps2 );; gap> ForAll(grps, CheckGeneratorsInvertible); true +gap> ForAll(grps, CheckField); +true gap> ForAll(grps, CheckBilinearForm); true gap> ForAll(grps, CheckQuadraticForm); true gap> ForAll(grps, CheckSize); true +gap> ForAll(grps1, CheckMembershipQuadratic); +true +gap> ForAll(grps2, CheckMembershipQuadratic2); +true # odd-dimensional special orthogonal groups -gap> grps:=[];; -gap> for d in [3,5,7] do +gap> grps1:=[];; +gap> grps2:=[];; +gap> for d in [1,3,5,7] do > for q in [2,3,4,5,7,8,9,16,17,25,27] do -> Add(grps, SO(d,q)); -> Add(grps, SO(d,q) ^ RandomInvertibleMat(d,GF(q))); -> Add(grps, SO(d,q) ^ RandomInvertibleMat(d,GF(q^2))); +> Add(grps1, SO(d,q)); +> Add(grps2, SO(d,q) ^ RandomInvertibleMat(d,GF(q))); +> Add(grps2, SO(d,q) ^ RandomInvertibleMat(d,GF(q^2))); > od; > od; +gap> grps:= Concatenation( grps1, grps2 );; gap> ForAll(grps, CheckGeneratorsSpecial); true +gap> ForAll(grps, CheckField); +true gap> ForAll(grps, CheckBilinearForm); true gap> ForAll(grps, CheckQuadraticForm); true gap> ForAll(grps, CheckSize); true +gap> ForAll(grps1, CheckMembershipQuadratic); +true +gap> ForAll(grps2, CheckMembershipQuadratic2); +true # even-dimensional special orthogonal groups -gap> grps:=[];; +gap> grps1:=[];; +gap> grps2:=[];; gap> for d in [2,4,6,8] do > for q in [2,3,4,5,7,8,9,16,17,25,27] do -> Add(grps, SO(+1,d,q)); -> Add(grps, SO(-1,d,q)); -> Add(grps, SO(+1,d,q) ^ RandomInvertibleMat(d,GF(q))); -> Add(grps, SO(-1,d,q) ^ RandomInvertibleMat(d,GF(q))); -> Add(grps, SO(+1,d,q) ^ RandomInvertibleMat(d,GF(q^2))); -> Add(grps, SO(-1,d,q) ^ RandomInvertibleMat(d,GF(q^2))); +> Add(grps1, SO(+1,d,q)); +> Add(grps1, SO(-1,d,q)); +> Add(grps2, SO(+1,d,q) ^ RandomInvertibleMat(d,GF(q))); +> Add(grps2, SO(-1,d,q) ^ RandomInvertibleMat(d,GF(q))); +> Add(grps2, SO(+1,d,q) ^ RandomInvertibleMat(d,GF(q^2))); +> Add(grps2, SO(-1,d,q) ^ RandomInvertibleMat(d,GF(q^2))); > od; > od; +gap> grps:= Concatenation( grps1, grps2 );; gap> ForAll(grps, CheckGeneratorsSpecial); true +gap> ForAll(grps, CheckField); +true gap> ForAll(grps, CheckBilinearForm); true gap> ForAll(grps, CheckQuadraticForm); true gap> ForAll(grps, CheckSize); true +gap> ForAll(grps1, CheckMembershipQuadratic); +true +gap> ForAll(grps2, CheckMembershipQuadratic2); +true # # Omega subgroups of special orthogonal groups @@ -133,7 +225,7 @@ true # odd-dimensional gap> grps:=[];; -gap> for d in [3,5,7] do +gap> for d in [1,3,5,7] do > for q in [2,3,4,5,7,8,9,16,17,25,27] do > Add(grps, Omega(d,q)); > Add(grps, Omega(d,q) ^ RandomInvertibleMat(d,GF(q))); @@ -142,6 +234,8 @@ gap> for d in [3,5,7] do > od; gap> ForAll(grps, CheckGeneratorsSpecial); true +gap> ForAll(grps, CheckField); +true gap> ForAll(grps, CheckBilinearForm); true gap> ForAll(grps, CheckQuadraticForm); @@ -163,6 +257,8 @@ gap> for d in [2,4,6,8] do > od; gap> ForAll(grps, CheckGeneratorsSpecial); true +gap> ForAll(grps, CheckField); +true gap> ForAll(grps, CheckBilinearForm); true gap> ForAll(grps, CheckQuadraticForm); @@ -175,18 +271,26 @@ true # # general unitary groups -gap> grps:=[];; +gap> grps1:=[];; +gap> grps2:=[];; gap> for d in [1..6] do > for q in [2,3,4,5,7,8,9,16,17,25,27] do -> Add(grps, GU(d,q)); +> Add(grps1, GU(d,q)); +> Add(grps1, GU(d,q) ^ RandomInvertibleMat(d,GF(q^2))); +> Add(grps2, GU(d,q) ^ RandomInvertibleMat(d,GF(q^4))); > od; > od; +gap> grps:= Concatenation( grps1, grps2 );; gap> ForAll(grps, CheckGeneratorsInvertible); true -gap> ForAll(grps, CheckSesquilinearForm); +gap> ForAll(grps, CheckField); +true +gap> ForAll(grps1, CheckSesquilinearForm); true gap> ForAll(grps, CheckSize); true +gap> ForAll(grps1, CheckClasses); +true # special unitary groups gap> grps:=[];; @@ -197,28 +301,49 @@ gap> for d in [1..6] do > od; gap> ForAll(grps, CheckGeneratorsInvertible); true +gap> ForAll(grps, CheckField); +true gap> ForAll(grps, CheckSesquilinearForm); true gap> ForAll(grps, CheckSize); true +gap> ForAll(grps, CheckClasses); +true +gap> ForAll(grps, CheckMembershipSesquilinear); +true # # symplectic groups # -gap> grps:=[];; +gap> grps1:=[];; +gap> grps2:=[];; gap> for d in [2,4,6,8] do > for q in [2,3,4,5,7,8,9,16,17,25,27] do -> Add(grps, Sp(d,q)); -> Add(grps, Sp(d,q) ^ RandomInvertibleMat(d,GF(q))); -> Add(grps, Sp(d,q) ^ RandomInvertibleMat(d,GF(q^2))); +> Add(grps1, Sp(d,q)); +> Add(grps2, Sp(d,q) ^ RandomInvertibleMat(d,GF(q))); +> Add(grps2, Sp(d,q) ^ RandomInvertibleMat(d,GF(q^2))); > od; > od; +gap> grps:= Concatenation( grps1, grps2 );; gap> ForAll(grps, CheckGeneratorsSpecial); true +gap> ForAll(grps, CheckField); +true gap> ForAll(grps, CheckBilinearForm); true gap> ForAll(grps, CheckSize); true +gap> ForAll(grps1, CheckMembershipBilinear); +true +gap> ForAll(grps2, CheckMembershipBilinear2); +true + +# an undocumented helper function +gap> G:= GeneralOrthogonalGroup( 3, GF(5) );; +gap> m:= [ [ 0, 1, 0 ], [ 0, 0, 0 ], [ 0, 0, 1 ] ] * Z(5)^0;; +gap> SetInvariantQuadraticFormFromMatrix( G, m ); +Error, only the three argument variant of SetInvariantQuadraticFormFromMatrix \ +is supported # gap> STOP_TEST("classic-forms.tst");