Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/forms/lib/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 5.4.2025 mit Größe 32 kB image not shown  

Quelle  classic.gi   Sprache: unbekannt

 
#############################################################################
##
##  classic.gi            'Forms' package
##
##  Provide the methods for 'GO', 'SO', 'Omega', 'GU', 'SU', and 'Sp' that
##  involve a prescribed invariant form.
##


# Compatibility with GAP < 4.12
if not IsBound(IsMatrixOrMatrixObj) then
    BindGlobal("IsMatrixOrMatrixObj", IsMatrixObj);
fi;

# We cannot use the function 'IsEqualProjective' from the recog package
# because the matrices that describe forms can have zero rows.
BindGlobal( "_IsEqualModScalars",
    function( mat1, mat2 )
    local m, n, i, j, s;

    m:= NrRows( mat1 );
    if m <> NrRows( mat2 ) then
      return false;
    fi;
    n:= NrCols( mat1 );
    if n <> NrCols( mat2 ) then
      return false;
    fi;
    for i in [ 1 .. m ] do
      for j in [ 1 .. n ] do
        if not IsZero( mat1[ i, j ] ) then
          s:= mat2[ i, j ] / mat1[ i, j ];
          if IsZero( s ) then
            return false;
          elif IsRowListMatrix( mat1 ) and IsRowListMatrix( mat2 ) then
            # separate case for performance reasons
            return ForAll( [ 1 .. m ], i -> s * mat1[i] = mat2[i] );
          fi;
          return s * mat1 = mat2;
        fi;
      od;
    od;
    return IsZero( mat2 );
end );

BindGlobal("Forms_OrthogonalGroup",
    function( g, form )
    local stored, gf, d, wanted, mat1, mat2, mat, matinv, gens, gg;

    stored:= InvariantQuadraticForm( g ).matrix;

    # If the prescribed form fits then just return.
    if stored = form!.matrix then
      return g;
    fi;

    gf:= FieldOfMatrixGroup( g );
    d:= DimensionOfMatrixGroup( g );

    # Compute a base change matrix.
    # (Check that the canonical forms are equal.)
    wanted:= QuadraticFormByMatrix( stored, gf );
    mat1:= BaseChangeToCanonical( form );
    mat2:= BaseChangeToCanonical( wanted );
    if not _IsEqualModScalars(
               Forms_RESET( mat1 * form!.matrix * TransposedMat( mat1 ) ),
               Forms_RESET( mat2 * stored * TransposedMat( mat2 ) ) ) then
      Error( "canonical forms of <form> and <wanted> differ" );
    fi;
    mat:= mat2^-1 * mat1;
    matinv:= mat^-1;

    # Create the group w.r.t. the prescribed form.
    gens:= List( GeneratorsOfGroup( g ), x -> matinv * x * mat );
    gg:= GroupWithGenerators( gens );

    UseIsomorphismRelation( g, gg );

    if HasName( g ) then
      SetName( gg, Name( g ) );
    fi;

    SetInvariantQuadraticForm( gg, rec( matrix:= form!.matrix ) );
    if HasIsFullSubgroupGLorSLRespectingQuadraticForm( g ) then
      SetIsFullSubgroupGLorSLRespectingQuadraticForm( gg,
          IsFullSubgroupGLorSLRespectingQuadraticForm( g ) );
    fi;

    mat:= matinv * InvariantBilinearForm( g ).matrix * TransposedMat( matinv );
    SetInvariantBilinearForm( gg, rec( matrix:= mat ) );
    if Characteristic( gf ) <> 2 and
       HasIsFullSubgroupGLorSLRespectingBilinearForm( g ) then
      SetIsFullSubgroupGLorSLRespectingBilinearForm( gg,
          IsFullSubgroupGLorSLRespectingBilinearForm( g ) );
    fi;

    return gg;
end );


#############################################################################
##
#O  GeneralOrthogonalGroupCons( <filter>, <form> )
#O  GeneralOrthogonalGroupCons( <filter>, <e>, <d>, <q>, <form> )
#O  GeneralOrthogonalGroupCons( <filter>, <e>, <d>, <R>, <form> )
##
##  'GeneralOrthogonalGroup' is a plain function that is defined in the GAP
##  library.
##  It calls 'GeneralOrthogonalGroupCons',
##  thus we have to declare the variants involving a quadratic form,
##  and install the corresponding methods.
##
Perform(
    [ IsMatrixOrMatrixObj, IsQuadraticForm, IsGroup and HasInvariantQuadraticForm ],
    function( obj )
      DeclareConstructor( "GeneralOrthogonalGroupCons",
        [ IsGroup, obj ] );
      DeclareConstructor( "GeneralOrthogonalGroupCons",
        [ IsGroup, IsInt, IsPosInt, IsPosInt, obj ] );
      DeclareConstructor( "GeneralOrthogonalGroupCons",
        [ IsGroup, IsInt, IsPosInt, IsRing, obj ] );
    end );


#############################################################################
##
#M  GeneralOrthogonalGroupCons( <filt>, <form> )
##
InstallMethod( GeneralOrthogonalGroupCons,
    "matrix group for matrix of form",
    [ IsMatrixGroup and IsFinite, IsMatrixOrMatrixObj ],
    { filt, mat } -> GeneralOrthogonalGroupCons( filt,
                       QuadraticFormByMatrix( mat, BaseDomain( mat ) ) ) );

InstallMethod( GeneralOrthogonalGroupCons,
    "matrix group for group with form",
    [ IsMatrixGroup and IsFinite, IsGroup and HasInvariantQuadraticForm ],
    { filt, G } -> GeneralOrthogonalGroupCons( filt,
                     QuadraticFormByMatrix(
                       InvariantQuadraticForm( G ).matrix,
                       FieldOfMatrixGroup( G ) ) ) );

InstallMethod( GeneralOrthogonalGroupCons,
    "matrix group for form",
    [ IsMatrixGroup and IsFinite, IsQuadraticForm ],
    function( filt, form )
    local d, q, e;

    d:= NumberRows( form!.matrix );
    q:= Size( form!.basefield );
    if IsOddInt( d ) then
      e:= 0;
    elif IsEllipticForm( form ) then
      e:= -1;
    else
      e:= 1;
    fi;
    return GeneralOrthogonalGroupCons( filt, e, d, q, form );
end );


#############################################################################
##
#M  GeneralOrthogonalGroupCons( <filt>, <e>, <d>, <q>, <form> )
##
InstallMethod( GeneralOrthogonalGroupCons,
    "matrix group for <e>, dimension, finite field size, matrix of form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsPosInt,
      IsMatrixOrMatrixObj ],
    { filt, e, d, q, mat } -> GeneralOrthogonalGroupCons( filt, e, d, q,
                                QuadraticFormByMatrix( mat, GF(q) ) ) );

InstallMethod( GeneralOrthogonalGroupCons,
    "matrix group for <e>, dimension, finite field size, group with form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsPosInt,
      IsGroup and HasInvariantQuadraticForm ],
    { filt, e, d, q, G } -> GeneralOrthogonalGroupCons( filt, e, d, q,
                              QuadraticFormByMatrix(
                                InvariantQuadraticForm( G ).matrix, GF(q) ) ) );

InstallMethod( GeneralOrthogonalGroupCons,
    "matrix group for <e>, dimension, finite field size, form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsPosInt,
      IsQuadraticForm ],
    function( filt, e, d, q, form )
    local g, stored, wanted, mat1, mat2, mat, matinv, gens, gg;

    # Create the default generators and form.
    g:= GeneralOrthogonalGroupCons( filt, e, d, q );
    return Forms_OrthogonalGroup( g, form );
end );


#############################################################################
##
#M  GeneralOrthogonalGroupCons( <filt>, <e>, <d>, <R>, <form> )
##
InstallMethod( GeneralOrthogonalGroupCons,
    "matrix group for <e>, dimension, finite field, matrix of form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsField and IsFinite,
      IsMatrixOrMatrixObj ],
    { filt, e, d, F, form } -> GeneralOrthogonalGroupCons( filt, e, d,
                                 Size( F ),
                                 QuadraticFormByMatrix( form, F ) ) );

InstallMethod( GeneralOrthogonalGroupCons,
    "matrix group for <e>, dimension, finite field, group with form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsField and IsFinite,
      IsGroup and HasInvariantQuadraticForm ],
    { filt, e, d, F, G } -> GeneralOrthogonalGroupCons( filt, e, d,
                              Size( F ),
                              QuadraticFormByMatrix(
                                InvariantQuadraticForm( G ).matrix, F ) ) );

InstallMethod( GeneralOrthogonalGroupCons,
    "matrix group for <e>, dimension, finite field, form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsField and IsFinite,
      IsQuadraticForm ],
    { filt, e, d, F, form } -> GeneralOrthogonalGroupCons( filt, e, d,
                                 Size( F ), form ) );


#############################################################################
##
#O  SpecialOrthogonalGroupCons( <filter>, <form> )
#O  SpecialOrthogonalGroupCons( <filter>, <e>, <d>, <q>, <form> )
#O  SpecialOrthogonalGroupCons( <filter>, <e>, <d>, <R>, <form> )
##
##  'SpecialOrthogonalGroup' is a plain function that is defined in the GAP
##  library.
##  It calls 'SpecialOrthogonalGroupCons',
##  thus we have to declare the variants involving a quadratic form,
##  and install the corresponding methods.
##
Perform(
    [ IsMatrixOrMatrixObj, IsQuadraticForm, IsGroup and HasInvariantQuadraticForm ],
    function( obj )
      DeclareConstructor( "SpecialOrthogonalGroupCons",
        [ IsGroup, obj ] );
      DeclareConstructor( "SpecialOrthogonalGroupCons",
        [ IsGroup, IsInt, IsPosInt, IsPosInt, obj ] );
      DeclareConstructor( "SpecialOrthogonalGroupCons",
        [ IsGroup, IsInt, IsPosInt, IsRing, obj ] );
    end );


#############################################################################
##
#M  SpecialOrthogonalGroupCons( <filt>, <form> )
##
InstallMethod( SpecialOrthogonalGroupCons,
    "matrix group for matrix of form",
    [ IsMatrixGroup and IsFinite, IsMatrixOrMatrixObj ],
    { filt, mat } -> SpecialOrthogonalGroupCons( filt,
                       QuadraticFormByMatrix( mat, BaseDomain( mat ) ) ) );

InstallMethod( SpecialOrthogonalGroupCons,
    "matrix group for group with form",
    [ IsMatrixGroup and IsFinite, IsGroup and HasInvariantQuadraticForm ],
    { filt, G } -> SpecialOrthogonalGroupCons( filt,
                     QuadraticFormByMatrix(
                       InvariantQuadraticForm( G ).matrix,
                       FieldOfMatrixGroup( G ) ) ) );

InstallMethod( SpecialOrthogonalGroupCons,
    "matrix group for form",
    [ IsMatrixGroup and IsFinite, IsQuadraticForm ],
    function( filt, form )
    local d, q, e;

    d:= NumberRows( form!.matrix );
    q:= Size( form!.basefield );
    if IsOddInt( d ) then
      e:= 0;
    elif IsEllipticForm( form ) then
      e:= -1;
    else
      e:= 1;
    fi;
    return SpecialOrthogonalGroupCons( filt, e, d, q, form );
end );


#############################################################################
##
#M  SpecialOrthogonalGroupCons( <filt>, <e>, <d>, <q>, <form> )
##
InstallMethod( SpecialOrthogonalGroupCons,
    "matrix group for <e>, dimension, finite field size, matrix of form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsPosInt,
      IsMatrixOrMatrixObj ],
    { filt, e, d, q, mat } -> SpecialOrthogonalGroupCons( filt, e, d, q,
                                QuadraticFormByMatrix( mat, GF(q) ) ) );

InstallMethod( SpecialOrthogonalGroupCons,
    "matrix group for <e>, dimension, finite field size, group with form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsPosInt,
      IsGroup and HasInvariantQuadraticForm ],
    { filt, e, d, q, G } -> SpecialOrthogonalGroupCons( filt, e, d, q,
                              QuadraticFormByMatrix(
                                InvariantQuadraticForm( G ).matrix, GF(q) ) ) );

InstallMethod( SpecialOrthogonalGroupCons,
    "matrix group for <e>, dimension, finite field size, form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsPosInt,
      IsQuadraticForm ],
    function( filt, e, d, q, form )
    local g, stored, wanted, mat1, mat2, mat, matinv, gens, gg;

    # Create the default generators and form.
    g:= SpecialOrthogonalGroupCons( filt, e, d, q );
    return Forms_OrthogonalGroup( g, form );
end );


#############################################################################
##
#M  SpecialOrthogonalGroupCons( <filt>, <e>, <d>, <R>, <form> )
##
InstallMethod( SpecialOrthogonalGroupCons,
    "matrix group for <e>, dimension, finite field, matrix of form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsField and IsFinite,
      IsMatrixOrMatrixObj ],
    { filt, e, d, F, form } -> SpecialOrthogonalGroupCons( filt, e, d,
                                 Size( F ),
                                 QuadraticFormByMatrix( form, F ) ) );

InstallMethod( SpecialOrthogonalGroupCons,
    "matrix group for <e>, dimension, finite field, group with form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsField and IsFinite,
      IsGroup and HasInvariantQuadraticForm ],
    { filt, e, d, F, G } -> SpecialOrthogonalGroupCons( filt, e, d,
                              Size( F ),
                              QuadraticFormByMatrix(
                                InvariantQuadraticForm( G ).matrix, F ) ) );

InstallMethod( SpecialOrthogonalGroupCons,
    "matrix group for <e>, dimension, finite field, form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsField and IsFinite,
      IsQuadraticForm ],
    { filt, e, d, F, form } -> SpecialOrthogonalGroupCons( filt, e, d,
                                 Size( F ), form ) );


#############################################################################
##
#O  OmegaCons( <filt>, [<e>, <d>, <q>, ]<form> )
#O  Omega( [<filt>, ]<form> )
#O  Omega( [<filt>, ][<e>, ]<d>, <q>, <form> )
#O  Omega( [<filt>, ][<e>, ]<d>, <R>, <form> )
##
##  'Omega' is an operation hat is defined in the GAP library.
##  Thus we have to declare the variants involving a quadratic form,
##  and install the corresponding 'Omega' methods that call 'OmegaCons'.
##
##  Install the methods involving <form>, which may be either a matrix or
##  a quadratic form or a group with stored 'InvariantQuadraticForm'.
##  (The other methods have been installed in the GAP library.)
##
Perform(
    [ IsMatrixOrMatrixObj, IsQuadraticForm, IsGroup and HasInvariantQuadraticForm ],
    function( obj )
      DeclareConstructor( "OmegaCons", [ IsGroup, obj ] );
      DeclareConstructor( "OmegaCons", [ IsGroup, IsInt, IsPosInt, IsPosInt, obj ] );

      DeclareOperation( "Omega", [ obj ] );
      InstallMethod( Omega, [ obj ], x -> OmegaCons( IsMatrixGroup, x ) );

      DeclareOperation( "Omega", [ IsFunction, obj ] );
      InstallMethod( Omega, [ IsFunction, obj ], OmegaCons );

      DeclareOperation( "Omega", [ IsPosInt, IsPosInt, obj ] );
      InstallMethod( Omega, [ IsPosInt, IsPosInt, obj ],
        { d, q, x } -> OmegaCons( IsMatrixGroup, 0, d, q, x ) );

      DeclareOperation( "Omega", [ IsPosInt, IsRing, obj ] );
      InstallMethod( Omega, [ IsPosInt, IsField and IsFinite, obj ],
        { d, R, x } -> OmegaCons( IsMatrixGroup, 0, d, Size( R ), x ) );

      DeclareOperation( "Omega", [ IsFunction, IsPosInt, IsPosInt, obj ] );
      InstallMethod( Omega, [ IsFunction, IsPosInt, IsPosInt, obj ],
        { filt, d, q, x } -> OmegaCons( filt, 0, d, q, x ) );

      DeclareOperation( "Omega", [ IsFunction, IsPosInt, IsRing, obj ] );
      InstallMethod( Omega, [ IsFunction, IsPosInt, IsField and IsFinite, obj ],
        { filt, d, R, x } -> OmegaCons( filt, 0, d, Size( R ), x ) );

      DeclareOperation( "Omega", [ IsInt, IsPosInt, IsPosInt, obj ] );
      InstallMethod( Omega, [ IsInt, IsPosInt, IsPosInt, obj ],
        { e, d, q, x } -> OmegaCons( IsMatrixGroup, e, d, q, x ) );

      DeclareOperation( "Omega", [ IsInt, IsPosInt, IsRing, obj ] );
      InstallMethod( Omega, [ IsInt, IsPosInt, IsField and IsFinite, obj ],
        { e, d, R, x } -> OmegaCons( IsMatrixGroup, e, d, Size( R ), x ) );

      DeclareOperation( "Omega", [ IsFunction, IsInt, IsPosInt, IsPosInt, obj ] );
      InstallMethod( Omega, [ IsFunction, IsInt, IsPosInt, IsPosInt, obj ],
        OmegaCons );

      DeclareOperation( "Omega", [ IsFunction, IsInt, IsPosInt, IsRing, obj ] );
      InstallMethod( Omega, [ IsFunction, IsInt, IsPosInt, IsField and IsFinite, obj ],
        { filt, e, d, R, x } -> OmegaCons( filt, e, d, Size( R ), x ) );
    end );


#############################################################################
##
#M  OmegaCons( <filt>, <form> )
##
InstallMethod( OmegaCons,
    "matrix group for matrix of form",
    [ IsMatrixGroup and IsFinite, IsMatrixOrMatrixObj ],
    { filt, mat } -> OmegaCons( filt,
                       QuadraticFormByMatrix( mat, BaseDomain( mat ) ) ) );

InstallMethod( OmegaCons,
    "matrix group for group with form",
    [ IsMatrixGroup and IsFinite, IsGroup and HasInvariantQuadraticForm ],
    { filt, G } -> OmegaCons( filt,
                     QuadraticFormByMatrix(
                       InvariantQuadraticForm( G ).matrix,
                       FieldOfMatrixGroup( G ) ) ) );

InstallMethod( OmegaCons,
    "matrix group for form",
    [ IsMatrixGroup and IsFinite, IsQuadraticForm ],
    function( filt, form )
    local d, q, e;

    d:= NumberRows( form!.matrix );
    q:= Size( form!.basefield );
    if IsOddInt( d ) then
      e:= 0;
    elif IsEllipticForm( form ) then
      e:= -1;
    else
      e:= 1;
    fi;
    return OmegaCons( filt, e, d, q, form );
end );


#############################################################################
##
#M  OmegaCons( <filt>, <e>, <d>, <q>, <form> )
##
InstallMethod( OmegaCons,
    "matrix group for <e>, dimension, finite field size, matrix of form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsPosInt,
      IsMatrixOrMatrixObj ],
    { filt, e, d, q, mat } -> OmegaCons( filt, e, d, q,
                                QuadraticFormByMatrix( mat, GF(q) ) ) );

InstallMethod( OmegaCons,
    "matrix group for <e>, dimension, finite field size, group with form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsPosInt,
      IsGroup and HasInvariantQuadraticForm ],
    { filt, e, d, q, G } -> OmegaCons( filt, e, d, q,
                              QuadraticFormByMatrix(
                                InvariantQuadraticForm( G ).matrix, GF(q) ) ) );

InstallMethod( OmegaCons,
    "matrix group for <e>, dimension, finite field size, form",
    [ IsMatrixGroup and IsFinite,
      IsInt,
      IsPosInt,
      IsPosInt,
      IsQuadraticForm ],
    function( filt, e, d, q, form )
    local g, stored, wanted, mat1, mat2, mat, matinv, gens, gg;

    # Create the default generators and form.
    g:= OmegaCons( filt, e, d, q );
    return Forms_OrthogonalGroup( g, form );
end );


#############################################################################
##
#O  GeneralUnitaryGroupCons( <filter>, <form> )
#O  GeneralUnitaryGroupCons( <filter>, <d>, <q>, <form> )
##
##  'GeneralUnitaryGroup' is a plain function that is defined in the GAP
##  library.
##  It calls 'GeneralUnitaryGroupCons',
##  thus we have to declare the variants involving a quadratic form,
##  and install the corresponding methods.
##
Perform(
    [ IsMatrixOrMatrixObj, IsHermitianForm, IsGroup and HasInvariantSesquilinearForm ],
    function( obj )
      DeclareConstructor( "GeneralUnitaryGroupCons", [ IsGroup, obj ] );
      DeclareConstructor( "GeneralUnitaryGroupCons",
        [ IsGroup, IsPosInt, IsPosInt, obj ] );
    end );


#############################################################################
##
#M  GeneralUnitaryGroupCons( <filt>, <form> )
##
InstallMethod( GeneralUnitaryGroupCons,
    "matrix group for matrix of form",
    [ IsMatrixGroup and IsFinite, IsMatrixOrMatrixObj ],
    function( filt, mat )
    local q, form;

    # Guess the intended field.
    q:= Size( BaseDomain( mat ) );
    if q = RootInt( q, 2 )^2 then
      form:= HermitianFormByMatrix( mat, GF(q) );
    else
      form:= HermitianFormByMatrix( mat, GF(q^2) );
    fi;
    return GeneralUnitaryGroupCons( filt, form );
    end );

InstallMethod( GeneralUnitaryGroupCons,
    "matrix group for group with form",
    [ IsMatrixGroup and IsFinite, IsGroup and HasInvariantSesquilinearForm ],
    { filt, G } -> GeneralUnitaryGroupCons( filt,
                     HermitianFormByMatrix(
                       InvariantSesquilinearForm( G ).matrix,
                       FieldOfMatrixGroup( G ) ) ) );

InstallMethod( GeneralUnitaryGroupCons,
    "matrix group for form",
    [ IsMatrixGroup and IsFinite, IsHermitianForm ],
    { filt, form } -> GeneralUnitaryGroupCons( filt,
                        NumberRows( form!.matrix ),
                        RootInt( Size( form!.basefield ), 2 ), form ) );

#############################################################################
##
#F  TransposedFrobeniusMat( <mat>, <qq> )
##  Helper function 
##
InstallGlobalFunction( TransposedFrobeniusMat,
  function( mat, qq )
    local   i,  j;
    mat:=MutableTransposedMat(mat);
    for i  in [ 1 .. NrRows(mat) ]  do
        for j  in [ 1 .. NrCols(mat) ]  do
            mat[i,j] := mat[i,j]^qq;
        od;
    od;
    return mat;
end );

#############################################################################
##
#M  GeneralUnitaryGroupCons( <filt>, <d>, <q>, <form> )
##
InstallMethod( GeneralUnitaryGroupCons,
    "matrix group for dimension, finite field size, matrix of form",
    [ IsMatrixGroup and IsFinite,
      IsPosInt,
      IsPosInt,
      IsMatrixOrMatrixObj ],
    { filt, d, q, mat } -> GeneralUnitaryGroupCons( filt, d, q,
                             HermitianFormByMatrix( mat, GF(q^2) ) ) );

InstallMethod( GeneralUnitaryGroupCons,
    "matrix group for dimension, finite field size, group with form",
    [ IsMatrixGroup and IsFinite,
      IsPosInt,
      IsPosInt,
      IsGroup and HasInvariantSesquilinearForm ],
    { filt, d, q, G } -> GeneralUnitaryGroupCons( filt, d, q,
                           HermitianFormByMatrix(
                             InvariantSesquilinearForm( G ).matrix, GF(q^2) ) ) );

InstallMethod( GeneralUnitaryGroupCons,
    "matrix group for dimension, finite field size, form",
    [ IsMatrixGroup and IsFinite,
      IsPosInt,
      IsPosInt,
      IsHermitianForm ],
    function( filt, d, q, form )
    local g, stored, wanted, mat1, mat2, mat, matinv, gens, gg;

    # Create the default generators and form.
    g:= GeneralUnitaryGroupCons( filt, d, q );
    stored:= InvariantSesquilinearForm( g ).matrix;

    # If the prescribed form fits then just return.
    if stored = form!.matrix then
      return g;
    fi;

    # Compute a base change matrix.
    # (Check that the canonical forms are equal.)
    wanted:= HermitianFormByMatrix( stored, GF(q^2) );
    mat1:= BaseChangeToCanonical( form );
    mat2:= BaseChangeToCanonical( wanted );
    if mat1 * form!.matrix * TransposedFrobeniusMat( mat1, q ) <>
       mat2 * stored * TransposedFrobeniusMat( mat2, q ) then
      Error( "canonical forms of <form> and <wanted> differ" );
    fi;
    mat:= mat2^-1 * mat1;
    matinv:= mat^-1;

    # Create the group w.r.t. the prescribed form.
    gens:= List( GeneratorsOfGroup( g ), x -> matinv * x * mat );
    gg:= GroupWithGenerators( gens );

    UseIsomorphismRelation( g, gg );

    if HasName( g ) then
      SetName( gg, Name( g ) );
    fi;

    SetInvariantSesquilinearForm( gg, rec( matrix:= form!.matrix ) );
    if HasIsFullSubgroupGLorSLRespectingSesquilinearForm( g ) then
      SetIsFullSubgroupGLorSLRespectingSesquilinearForm( gg,
          IsFullSubgroupGLorSLRespectingSesquilinearForm( g ) );
    fi;

    return gg;
end );


#############################################################################
##
#O  SpecialUnitaryGroupCons( <filter>, <form> )
#O  SpecialUnitaryGroupCons( <filter>, <d>, <q>, <form> )
##
##  'SpecialUnitaryGroup' is a plain function that is defined in the GAP
##  library.
##  It calls 'SpecialUnitaryGroupCons',
##  thus we have to declare the variants involving a quadratic form,
##  and install the corresponding methods.
##
Perform(
    [ IsMatrixOrMatrixObj, IsHermitianForm, IsGroup and HasInvariantSesquilinearForm ],
    function( obj )
      DeclareConstructor( "SpecialUnitaryGroupCons", [ IsGroup, obj ] );
      DeclareConstructor( "SpecialUnitaryGroupCons",
        [ IsGroup, IsPosInt, IsPosInt, obj ] );
    end );


#############################################################################
##
#M  SpecialUnitaryGroupCons( <filt>, <form> )
##
InstallMethod( SpecialUnitaryGroupCons,
    "matrix group for matrix of form",
    [ IsMatrixGroup and IsFinite, IsMatrixOrMatrixObj ],
    function( filt, mat )
    local q, form;

    # Guess the intended field.
    q:= Size( BaseDomain( mat ) );
    if q = RootInt( q, 2 )^2 then
      form:= HermitianFormByMatrix( mat, GF(q) );
    else
      form:= HermitianFormByMatrix( mat, GF(q^2) );
    fi;
    return SpecialUnitaryGroupCons( filt, form );
    end );

InstallMethod( SpecialUnitaryGroupCons,
    "matrix group for group with form",
    [ IsMatrixGroup and IsFinite, IsGroup and HasInvariantSesquilinearForm ],
    { filt, G } -> SpecialUnitaryGroupCons( filt,
                     HermitianFormByMatrix(
                       InvariantSesquilinearForm( G ).matrix,
                       FieldOfMatrixGroup( G ) ) ) );

InstallMethod( SpecialUnitaryGroupCons,
    "matrix group for form",
    [ IsMatrixGroup and IsFinite, IsHermitianForm ],
    { filt, form } -> SpecialUnitaryGroupCons( filt,
                        NumberRows( form!.matrix ),
                        RootInt( Size( form!.basefield ), 2 ), form ) );


#############################################################################
##
#M  SpecialUnitaryGroupCons( <filt>, <d>, <q>, <form> )
##
InstallMethod( SpecialUnitaryGroupCons,
    "matrix group for dimension, finite field size, matrix of form",
    [ IsMatrixGroup and IsFinite,
      IsPosInt,
      IsPosInt,
      IsMatrixOrMatrixObj ],
    { filt, d, q, mat } -> SpecialUnitaryGroupCons( filt, d, q,
                             HermitianFormByMatrix( mat, GF(q^2) ) ) );

InstallMethod( SpecialUnitaryGroupCons,
    "matrix group for dimension, finite field size, group with form",
    [ IsMatrixGroup and IsFinite,
      IsPosInt,
      IsPosInt,
      IsGroup and HasInvariantSesquilinearForm ],
    { filt, d, q, G } -> SpecialUnitaryGroupCons( filt, d, q,
                           HermitianFormByMatrix(
                             InvariantSesquilinearForm( G ).matrix, GF(q^2) ) ) );

InstallMethod( SpecialUnitaryGroupCons,
    "matrix group for dimension, finite field size, form",
    [ IsMatrixGroup and IsFinite,
      IsPosInt,
      IsPosInt,
      IsHermitianForm ],
    function( filt, d, q, form )
    local g, stored, wanted, mat1, mat2, mat, matinv, gens, gg;

    # Create the default generators and form.
    g:= SpecialUnitaryGroupCons( filt, d, q );
    stored:= InvariantSesquilinearForm( g ).matrix;

    # If the prescribed form fits then just return.
    if stored = form!.matrix then
      return g;
    fi;

    # Compute a base change matrix.
    # (Check that the canonical forms are equal.)
    wanted:= HermitianFormByMatrix( stored, GF(q^2) );
    mat1:= BaseChangeToCanonical( form );
    mat2:= BaseChangeToCanonical( wanted );
    if mat1 * form!.matrix * TransposedFrobeniusMat( mat1, q ) <>
       mat2 * stored * TransposedFrobeniusMat( mat2, q ) then
      Error( "canonical forms of <form> and <wanted> differ" );
    fi;
    mat:= mat2^-1 * mat1;
    matinv:= mat^-1;

    # Create the group w.r.t. the prescribed form.
    gens:= List( GeneratorsOfGroup( g ), x -> matinv * x * mat );
    gg:= GroupWithGenerators( gens );

    UseIsomorphismRelation( g, gg );

    if HasName( g ) then
      SetName( gg, Name( g ) );
    fi;

    SetInvariantSesquilinearForm( gg, rec( matrix:= form!.matrix ) );
    if HasIsFullSubgroupGLorSLRespectingSesquilinearForm( g ) then
      SetIsFullSubgroupGLorSLRespectingSesquilinearForm( gg,
          IsFullSubgroupGLorSLRespectingSesquilinearForm( g ) );
    fi;

    return gg;
end );


#############################################################################
##
#O  SymplecticGroupCons( <filter>, <form> )
#O  SymplecticGroupCons( <filter>, <d>, <q>, <form> )
#O  SymplecticGroupCons( <filter>, <d>, <R>, <form> )
##
##  'SymplecticGroup' is a plain function that is defined in the GAP
##  library.
##  It calls 'SymplecticGroupCons',
##  thus we have to declare the variants involving a quadratic form,
##  and install the corresponding methods.
##
Perform(
    [ IsMatrixOrMatrixObj, IsBilinearForm, IsGroup and HasInvariantBilinearForm ],
    function( obj )
      DeclareConstructor( "SymplecticGroupCons", [ IsGroup, obj ] );
      DeclareConstructor( "SymplecticGroupCons",
        [ IsGroup, IsPosInt, IsPosInt, obj ] );
      DeclareConstructor( "SymplecticGroupCons",
        [ IsGroup, IsPosInt, IsRing, obj ] );
    end );


#############################################################################
##
#M  SymplecticGroupCons( <filt>, <form> )
##
InstallMethod( SymplecticGroupCons,
    "matrix group for matrix of form",
    [ IsMatrixGroup and IsFinite, IsMatrixOrMatrixObj ],
    { filt, mat } -> SymplecticGroupCons( filt,
                       BilinearFormByMatrix( mat, BaseDomain( mat ) ) ) );

InstallMethod( SymplecticGroupCons,
    "matrix group for group with form",
    [ IsMatrixGroup and IsFinite, IsGroup and HasInvariantBilinearForm ],
    { filt, G } -> SymplecticGroupCons( filt,
                     BilinearFormByMatrix(
                       InvariantBilinearForm( G ).matrix,
                       FieldOfMatrixGroup( G ) ) ) );

InstallMethod( SymplecticGroupCons,
    "matrix group for form",
    [ IsMatrixGroup and IsFinite, IsBilinearForm ],
    { filt, form } -> SymplecticGroupCons( filt,
                        NumberRows( form!.matrix ),
                        Size( form!.basefield ), form ) );


#############################################################################
##
#M  SymplecticGroupCons( <filt>, <d>, <q>, <form> )
##
InstallMethod( SymplecticGroupCons,
    "matrix group for dimension, finite field size, matrix of form",
    [ IsMatrixGroup and IsFinite,
      IsPosInt,
      IsPosInt,
      IsMatrixOrMatrixObj ],
    { filt, d, q, mat } -> SymplecticGroupCons( filt, d, q,
                             BilinearFormByMatrix( mat, GF(q) ) ) );

InstallMethod( SymplecticGroupCons,
    "matrix group for dimension, finite field size, group with form",
    [ IsMatrixGroup and IsFinite,
      IsPosInt,
      IsPosInt,
      IsGroup and HasInvariantBilinearForm ],
    { filt, d, q, G } -> SymplecticGroupCons( filt, d, q,
                           BilinearFormByMatrix(
                             InvariantBilinearForm( G ).matrix, GF(q) ) ) );

InstallMethod( SymplecticGroupCons,
    "matrix group for dimension, finite field size, form",
    [ IsMatrixGroup and IsFinite,
      IsPosInt,
      IsPosInt,
      IsBilinearForm ],
    function( filt, d, q, form )
    local g, stored, wanted, mat1, mat2, mat, matinv, gens, gg;

    # Create the default generators and form.
    g:= SymplecticGroupCons( filt, d, q );
    stored:= InvariantBilinearForm( g ).matrix;

    # If the prescribed form fits then just return.
    if stored = form!.matrix then
      return g;
    fi;

    # Compute a base change matrix.
    # (Check that the canonical forms are equal.)
    wanted:= BilinearFormByMatrix( stored, GF(q) );
    mat1:= BaseChangeToCanonical( form );
    mat2:= BaseChangeToCanonical( wanted );
    if mat1 * form!.matrix * TransposedMat( mat1 ) <>
       mat2 * stored * TransposedMat( mat2 ) then
      Error( "canonical forms of <form> and <wanted> differ" );
    fi;
    mat:= mat2^-1 * mat1;
    matinv:= mat^-1;

    # Create the group w.r.t. the prescribed form.
    gens:= List( GeneratorsOfGroup( g ), x -> matinv * x * mat );
    gg:= GroupWithGenerators( gens );

    UseIsomorphismRelation( g, gg );

    if HasName( g ) then
      SetName( gg, Name( g ) );
    fi;

    SetInvariantBilinearForm( gg, rec( matrix:= form!.matrix ) );
    if HasIsFullSubgroupGLorSLRespectingBilinearForm( g ) then
      SetIsFullSubgroupGLorSLRespectingBilinearForm( gg,
          IsFullSubgroupGLorSLRespectingBilinearForm( g ) );
    fi;

    return gg;
end );


#############################################################################
##
#M  SymplecticGroupCons( <filt>, <d>, <R>, <form> )
##
InstallMethod( SymplecticGroupCons,
    "matrix group for dimension, finite field, matrix of form",
    [ IsMatrixGroup and IsFinite,
      IsPosInt,
      IsField and IsFinite,
      IsMatrixOrMatrixObj ],
    { filt, d, F, form } -> SymplecticGroupCons( filt, d, Size( F ),
                              BilinearFormByMatrix( form, F ) ) );

InstallMethod( SymplecticGroupCons,
    "matrix group for dimension, finite field, group with form",
    [ IsMatrixGroup and IsFinite,
      IsPosInt,
      IsField and IsFinite,
      IsGroup and HasInvariantBilinearForm ],
    { filt, d, F, G } -> SymplecticGroupCons( filt, d, Size( F ),
                           BilinearFormByMatrix(
                             InvariantBilinearForm( G ).matrix, F ) ) );

InstallMethod( SymplecticGroupCons,
    "matrix group for dimension, finite field, form",
    [ IsMatrixGroup and IsFinite,
      IsPosInt,
      IsField and IsFinite,
      IsBilinearForm ],
    { filt, d, F, form } -> SymplecticGroupCons( filt, d, Size( F ), form ) );

[ Dauer der Verarbeitung: 0.41 Sekunden  (vorverarbeitet)  ]