Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  fieldfin.gi   Sprache: unbekannt

 
#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Werner Nickel, Martin Schönert.
##
##  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  finite  fields.    Note that  we must
##  distinguish finite fields and fields that  consist of `FFE's.  (The image
##  of the natural embedding of the field  `GF(<q>)' into a field of rational
##  functions is of  course a finite field  but  its elements are  not `FFE's
##  since this would be a property given by their family.)
##
##  Special methods for `FFE's can be found in the file `ffe.gi'.
##
##  1. Miscellaneous Functions
##  2. Groups of FFEs
##  3. Bases of Finite Fields
##  4. Automorphisms of Finite Fields
##


#############################################################################
##
##  1. Miscellaneous Functions
##


#############################################################################
##
#M  GeneratorsOfLeftModule( <F> ) . . . .  the vectors of the canonical basis
##
InstallMethod( GeneratorsOfLeftModule,
    "for a finite field (return the vectors of the canonical basis)",
    [ IsField and IsFinite ],
    function( F )
    local z;
    z:= RootOfDefiningPolynomial( F );
    return List( [ 0 .. Dimension( F ) - 1 ], i -> z^i );
#T call of `UseBasis' ?
    end );


#############################################################################
##
#M  Random( <F> ) . . . . . . . . . . . .  random element from a finite field
##
##  We have special methods for finite prime fields and for fields with
##  primitive root, for efficiency reasons.
##  All other cases are handled by the vector space methods.
##
InstallMethodWithRandomSource( Random,
    "for a random source and a finite prime field",
    [ IsRandomSource, IsField and IsPrimeField and IsFinite ],
    { rs, F } -> Random(rs,1,Size(F)) * One( F ) );

InstallMethodWithRandomSource( Random,
    "for a random source and a finite field with known primitive root",
    [ IsRandomSource, IsField and IsFinite and HasPrimitiveRoot ],
    function ( rs, F )
    local   rnd;
    rnd := Random( rs, 0, Size( F )-1 );
    if rnd = 0  then
      rnd := Zero( F );
    else
      rnd := PrimitiveRoot( F )^rnd;
    fi;
    return rnd;
    end );


#############################################################################
##
#M  Units( <F> )  . . . . . . . . . . . . . . . . . . . . via `PrimitiveRoot'
##
InstallMethod( Units,
    "for a finite field",
    [ IsField and IsFinite ],
    function ( F )
    local G;
    G := GroupByGenerators( [ PrimitiveRoot( F ) ] );
    if HasSize( F ) then
      SetSize( G, Size( F )-1 );
    fi;
    return G;
    end );


#############################################################################
##
#M  \=( <F>, <G> ) . . . . . . . . . . . . . . . . . .  for two finite fields
##
##  Note that for two finite fields in the same family,
##  it suffices to check the dimensions as vector spaces over the (common)
##  prime field.
##
InstallMethod( \=,
    "for two finite fields in the same family",
    IsIdenticalObj,
    [ IsField and IsFinite, IsField and IsFinite ],
    function ( F, G )
    return DegreeOverPrimeField( F ) = DegreeOverPrimeField( G );
    end );


#############################################################################
##
#M  IsSubset( <F>, <G> )  . . . . . . . . . . . . . . . for two finite fields
##
##  Note that for two finite fields in the same family,
##  it suffices to check the dimensions as vector spaces over the (common)
##  prime field.
##
InstallMethod( IsSubset,
    "for two finite fields in the same family",
    IsIdenticalObj,
    [ IsField and IsFinite, IsField and IsFinite ],
    function( F, G )
    return DegreeOverPrimeField( F ) mod DegreeOverPrimeField( G ) = 0;
    end );


#############################################################################
##
#M  Subfields( <F> )  . . . . . . . . . . . . . . subfields of a finite field
##
InstallMethod( Subfields,
    "for finite field of FFEs",
    [ IsField and IsFinite and IsFFECollection ],
    function( F )
    local d, p;
    d:= DegreeOverPrimeField( F );
    p:= Characteristic( F );
    return List( DivisorsInt( d ), n -> GF( p, n ) );
    end );

#############################################################################
##
#M  Subfields( <F> )  . . . . . . . . . . . . . . subfields of a finite field
##
InstallMethod( Subfields, "for finite fields that are not FFEs",
    [ IsField and IsFinite ],
function( F )
local d, p,l,i,mp,fac,S;
  d:= DegreeOverPrimeField( F );
  p:= Characteristic( F );
  l:=[];
  for i in Filtered(DivisorsInt(d),x->x<d) do
    mp:=MinimalPolynomial(GF(p),PrimitiveRoot(GF(p^i)));
    mp:=Value(mp,X(F),One(F));
    fac:=Factors(mp);
    fac:=RootsOfUPol(fac[1])[1]; # one root
    S:=FieldByGenerators([fac]);
    SetDegreeOverPrimeField(S,i);
    SetSize(S,p^i);
    # hack, as there is no good print routine for subfields
    SetName(S,Concatenation("Field([",String(fac),"])"));
    Add(l,S);
  od;
  Add(l,F); # field itself -- save on expensive factorization
  return l;
end );


#############################################################################
##
#M  PrimeField( <F> ) . . . . . . . . . . . . . . . . . .  for a finite field
##
InstallMethod( PrimeField,
    "for finite field of FFEs",
    [ IsField and IsFFECollection ],
    F -> GF( Characteristic( F ) ) );


#############################################################################
##
#M  MinimalPolynomial( <F>, <z>, <inum> )
##
InstallMethod( MinimalPolynomial,
    "finite field, finite field element, and indet. number",
    IsCollsElmsX,
    [ IsField and IsFinite, IsScalar, IsPosInt ],
function( F, z, inum )
    local   df,  dz,  q,  dd,  pol,  deg,  con,  i;

    # get the field in which <z> lies
    df := DegreeOverPrimeField(F);
    dz := DegreeOverPrimeField(DefaultField(z));
    q  := Size(F);
    dd := LcmInt(df,dz) / df;

    # compute the minimal polynomial simply by multiplying $x-cnj$
    pol := [ One(F) ];
    deg := 0;
    for con  in Set( [ 0 .. dd-1 ], x -> z^(q^x) )  do
        pol[deg+2] := pol[deg+1];
        for i  in [ deg+1, deg .. 2 ]  do
            pol[i] := pol[i-1] -  con*pol[i];
        od;
        pol[1] := -con*pol[1];
        deg := deg + 1;
    od;

    # return the coefficients list of the minimal polynomial
    return UnivariatePolynomial( F, pol, inum );
end );


#############################################################################
##
##  2. Groups of FFEs
##


#############################################################################
##
#M  IsHandledByNiceMonomorphism( <G> )  . . . . . . `true' for groups of FFEs
##
InstallTrueMethod( IsHandledByNiceMonomorphism,
    IsGroup and IsFFECollection );


#############################################################################
##
#M  IsCyclic( <G> ) . . . . . . . . . . . . . . . . groups of FFEs are cyclic
##
InstallTrueMethod( IsCyclic, IsGroup and IsFFECollection );


#############################################################################
##
#M  <elm> in <G>  . . . . . . . . . . . . . . . . . . . . via `PrimitiveRoot'
##
InstallMethod( \in,
    "for groups of FFE",
    IsElmsColls,
    [ IsFFE, IsGroup and IsFFECollection ],
    function( elm, G )
    local F;

    F:= Field( Concatenation( GeneratorsOfGroup( G ), [ One( G ) ] ) );
    return     elm in F and not IsZero( elm )
           and LogFFE( elm, PrimitiveRoot( F ) ) mod
               ( ( Size( F ) - 1 ) / Size( G ) ) = 0;
    end );


#############################################################################
##
#M  Size( <G> ) . . . . . . . . . . . . . . . . . . . . . via `PrimitiveRoot'
##
InstallMethod( Size,
    "for groups of FFE",
    [ IsGroup and IsFFECollection ],
    function( G )
    local   gens, F, z, k;

    if IsTrivial( G )  then
        return 1;
    fi;

    gens := GeneratorsOfGroup( G );
    F := Field( gens );
    z := PrimitiveRoot( F );
    k := Gcd( Integers, List( gens, g -> LogFFE(g, z) ) );
    return ( Size( F ) - 1 ) /  GcdInt(k, ( Size( F ) - 1 ));
end );


#############################################################################
##
#M  AbelianInvariants( <G> ) . . . . . . . . . . . . . .  via `PrimitiveRoot'
##
InstallMethod( AbelianInvariants,
    "for groups of FFE",
    [ IsGroup and IsFFECollection ],
    G -> AbelianInvariantsOfList( [Size( G )] ) );

#############################################################################
##
#M  CanEasilyComputeWithIndependentGensAbelianGroup( <G> )
##
InstallTrueMethod(CanEasilyComputeWithIndependentGensAbelianGroup,
    IsGroup and IsFFECollection);

#############################################################################
##
#M  IndependentGeneratorsOfAbelianGroup( <G> ) . . . . .  via `PrimitiveRoot'
##
InstallMethod( IndependentGeneratorsOfAbelianGroup,
    "for groups of FFE",
    [ IsGroup and IsFFECollection ],
    function( G )
    local   F, g, base, ord, o, cf, j;

    if IsTrivial( G )  then
        return [];
    fi;

    F := Field( GeneratorsOfGroup( G ) );
    g := PrimitiveRoot( F ) ^ ( ( Size( F ) - 1 ) / Size( G ) );
    base := [];
    ord := [];
    o := Order( g );
    cf:=Collected( Factors( o ) );
    for j in cf do
        j := j[1]^j[2];
        Add( base, g^(o/j) );
        Add( ord, j );
    od;
    SortParallel(ord,base);
    return base;
end );

#############################################################################
##
#M  IndependentGeneratorExponents( <G> ) . . . . . . . .  via `PrimitiveRoot'
##
InstallMethod( IndependentGeneratorExponents,
    "for groups of FFE",
    IsCollsElms,
    [ IsGroup and IsFFECollection, IsFFE ],
    function( G, elm )
    local   F, z, gens, j, exps;

    if IsTrivial( G )  then
        return [];
    fi;

    F := Field( GeneratorsOfGroup( G ) );
    z := PrimitiveRoot( F );
    gens := IndependentGeneratorsOfAbelianGroup( G );

    # We need to compute LogFFE for every element of gens, which is
    # in general quite expensive. But if gens was computed by our
    # IndependentGeneratorsOfAbelianGroup method, then we actually
    # know the LogFFE value. Since verifying this is cheap, try that
    # first before resorting to LogFFE.
    exps := List( gens, g -> ( Size(F) - 1 ) / Order( g ) );

    if ForAny( [ 1 .. Length(exps) ], i -> gens[i] <> z^exps[i] ) then
        # We have to do it the hard way...
        exps := List( gens, g -> LogFFE( g, z ) );
    fi;

    j := LogFFE( elm, z );
    exps := List( [1..Length(exps)], i -> ( j / exps[i] ) mod Order( gens[i] ) );

    Assert( 0, elm = Product( [1..Length(exps)], i -> gens[i]^exps[i]) );
    return exps;
end );


#############################################################################
##
##  3. Bases of Finite Fields
##
##  *Note*:  Bases of *subspaces* of fields which are themselves not fields
##  are handled by the mechanism of nice bases (see `field.gi').
##


#############################################################################
##
#R  IsBasisFiniteFieldRep( <F> )
##
##  Bases of finite fields in the representation `IsBasisFiniteFieldRep'
##  are dealt with as follows.
##
##  Coefficients w.r.t.~a basis $B = (b_0, b_1, \ldots, b_d)$ of the field
##  extension $GF(q^{d+1})$ over $GF(q)$ can be computed as follows.
##  $x \in GF(q^{d+1})$ is of the form $x = \sum_{i=0}^d a_i b_i$,
##  with $a_i \in GF(q)$, if and only if for $0 \leq k \leq d$ the equation
##  $x^{q^k} = \sum_{i=0}^d a_i b_i^{q^k}$ holds.
##  Thus we have the matrix equation
##  $$
##  [ x^{q^k} ]_{k=0}^d = [ a_i ]_{i=0}^d [ b_i^{q^k} ]_{i,k=0}^d ,
##  $$
##  from which the coefficients $a_i$ can be computed.
##  The inverse of the matrix $[ b_i^{q^k} ]_{i,k=0}^d$ is stored in the
##  basis as value of the component `inverseBase'.
##
DeclareRepresentation( "IsBasisFiniteFieldRep",
    IsAttributeStoringRep,
    [ "inverseBase", "d", "q" ] );

InstallTrueMethod( IsFinite, IsBasis and IsBasisFiniteFieldRep );


#############################################################################
##
#M  Basis( <F> )
##
##  We know a canonical basis for finite fields.
##
InstallMethod( Basis,
    "for a finite field (delegate to `CanonicalBasis')",
    [ IsField and IsFinite ], CANONICAL_BASIS_FLAGS,
    CanonicalBasis );


#############################################################################
##
#M  Basis( <F>, <gens> )
#M  BasisNC( <F>, <gens> )
##
InstallMethod( Basis,
    "for a finite field, and a hom. list",
    IsIdenticalObj,
    [ IsField and IsFinite, IsFFECollection and IsList ],
    function( F, gens )

    local B,     # the basis, result
          q,     # size of the subfield
          d,     # dimension of the extension
          mat,
          b,b1,
          cnjs,
          k;

    # Set up the basis object.
    B:= Objectify( NewType( FamilyObj( gens ),
                                IsFiniteBasisDefault
                            and IsBasisFiniteFieldRep ),
                   rec() );
    SetUnderlyingLeftModule( B, F );
    SetBasisVectors( B, gens );

    # Get the size `q' of the subfield and the dimension `d'
    # of the extension with respect to the subfield.
    q:= Size( LeftActingDomain( F ) );
    d:= Dimension( F );

    # Test that the basis vectors really define the
    # (unique) finite field extension of degree `d'.
    if d <> Length( gens ) then
      return fail;
    fi;

    # Build the matrix `M[i][k] = vectors[i]^(q^k)'.
    mat:= [];
    for b in gens do
        cnjs := [];
        b1 := b;
        cnjs := [b];
        for k in [ 1 .. d-1 ] do
            b1 := b1^q;
            Add( cnjs, b1 );
        od;
        Add( mat, cnjs );
    od;

    # We have a basis if and only if `mat' is invertible.
    if Length(mat) > 0 then
        mat:= Inverse( mat );
        if mat = fail then
            return fail;
        fi;
    else
        mat := Immutable(mat);
    fi;

    # Add the coefficients information.
    B!.inverseBase:= mat;
    B!.d:= d;
    B!.q:= q;

    # Return the basis.
    return B;
    end );

InstallMethod( BasisNC,
    "for a finite field, and a hom. list",
    IsIdenticalObj,
    [ IsField and IsFinite, IsFFECollection and IsList ], 10,
    function( F, gens )

    local B,     # the basis, result
          q,     # size of the subfield
          d,     # dimension of the extension
          mat,
          b,b1,
          cnjs,
          k;

    # Set up the basis object.
    B:= Objectify( NewType( FamilyObj( gens ),
                                IsFiniteBasisDefault
                            and IsBasisFiniteFieldRep ),
                   rec() );
    SetUnderlyingLeftModule( B, F );
    SetBasisVectors( B, gens );

    # Get the size `q' of the subfield and the dimension `d'
    # of the extension with respect to the subfield.
    q:= Size( LeftActingDomain( F ) );
    d:= Dimension( F );

    # Build the matrix `M[i][k] = vectors[i]^(q^k)'.
    mat:= [];
    for b in gens do
        cnjs := [b];
        b1 := b;
        for k in [ 1 .. d-1 ] do
            b1 := b1^q;
            Add( cnjs, b1 );
        od;
        Add( mat, cnjs );
    od;

    # Add the coefficients information.
    if Length(mat) > 0 then
        B!.inverseBase:= Inverse( mat );
    else
        B!.inverseBase:= Immutable(mat);
    fi;
    B!.d:= d;
    B!.q:= q;

    # Return the basis.
    return B;
    end );


#############################################################################
##
#M  Coefficients( <B>, <z> )  . . . . . . . . . . for basis of a finite field
##
InstallMethod( Coefficients,
    "for a basis of a finite field, and a scalar",
    IsCollsElms,
    [ IsBasis and IsBasisFiniteFieldRep, IsScalar ],
    function ( B, z )
    local   q, d, k, zz;

    if   not z in UnderlyingLeftModule( B ) then
      return fail;
    fi;

    # Get the size `q' of the subfield and the degree `d' of the extension
    # with respect to the subfield.
    q := B!.q;
    d := B!.d;

    # Compute the vector of conjugates of `z'.
    zz := [];
    for k  in [0..d-1]  do
        Add( zz, z^(q^k) );
    od;

    # The `inverseBase' component of the basis defines the base change
    # to the normal basis.
    return zz * B!.inverseBase;
    end );


#############################################################################
##
#M  LinearCombination( <B>, <coeffs> )
##
InstallMethod( LinearCombination,
    "for a basis of a finite field, and a hom. list",
    IsIdenticalObj,
    [ IsBasis and IsBasisFiniteFieldRep, IsHomogeneousList ],
        function ( B, coeffs )
    if Length(coeffs) = 0 then
        TryNextMethod();
    fi;
    return coeffs * BasisVectors( B );
#T This calls PROD_LIST_LIST_DEFAULT
#T if both lists are known to be small,
#T and PROD_LIST_LIST_TRY otherwise!
#T Is this method necessary at all??
    end );


#############################################################################
##
#M  CanonicalBasis( <F> )
##
##  The canonical basis of the finite field <F> with $p^n$ elements,
##  viewed over its subfield with $p^d$ elements,
##  consists of the vectors $<z>^i$, $0 \leq i \< n/d$,
##  where <z> is `RootOfDefiningPolynomial( <F> )'.
##
InstallMethod( CanonicalBasis,
    "for a finite field",
    [ IsField and IsFinite and IsFFECollection ],
    function( F )
    local z,         # primitive root
          B;         # basis record, result

    z:= RootOfDefiningPolynomial( F );
    B:= BasisNC( F, List( [ 0 .. Dimension( F ) - 1 ], i -> z ^ i ) );
    SetIsCanonicalBasis( B, true );

    # Return the basis object.
    return B;
    end );


#############################################################################
##
#M  NormalBase( <F>, <elm> )
##
##  For finite fields just search.
##
InstallMethod( NormalBase,
"for a finite field and scalar",
    [ IsField and IsFinite, IsScalar ],
function(F, b)
    local q, d, z, l, bas, i;
    if b=0*b then
        b := One(F);
    fi;
    q := Size(LeftActingDomain(F));
    d := Dimension(F);
    z := PrimitiveRoot(F);
    repeat
        l := [b];
        for i in [1..d-1] do
          Add(l, l[i]^q);
        od;
        bas := Basis(F, l);
        b := b*z;
    until bas <> fail;
    return l;
end);


#############################################################################
##
##  4. Automorphisms of Finite Fields
##


#############################################################################
##
#R  IsFrobeniusAutomorphism( <obj> )  . test if an object is a Frobenius aut.
##
DeclareRepresentation( "IsFrobeniusAutomorphism",
        IsFieldHomomorphism
    and IsMapping
    and IsAttributeStoringRep,
    [ "power" ] );


#############################################################################
##
#F  FrobeniusAutomorphism(<F>)  . .  Frobenius automorphism of a finite field
##
BindGlobal( "FrobeniusAutomorphismI", function ( F, i )

    local Fam, frob;

    # Catch the bad case.
    if Size( F ) = 2 then
      i:= 1;
    else
      i:= i mod ( Size( F ) - 1 );
    fi;

    if i = 1 then
      return IdentityMapping( F );
    fi;

    Fam:= ElementsFamily( FamilyObj( F ) );

    # make the mapping object
    frob:= Objectify( TypeOfDefaultGeneralMapping( F, F,
                              IsFrobeniusAutomorphism
                          and IsSPGeneralMapping
                          and IsRingWithOneHomomorphism
                          and IsBijective ),
                      rec() );

    frob!.power := i;

    return frob;
end );

InstallMethod( FrobeniusAutomorphism,
    "for a field",
    [ IsField ],
    function ( F )

    # check the arguments
    if not IsPosRat( Characteristic( F ) ) then
        Error( "<F> must be a field of nonzero characteristic" );
    fi;

    # return the automorphism
    return FrobeniusAutomorphismI( F, Characteristic( F ) );
end );


#############################################################################
##
#M  \=( <frob1>, <frob2> )
#M  \=( <id>, <frob> )
#M  \=( <frob>, <id> )
##
InstallMethod( \=,
    "for two Frobenius automorphisms",
    IsIdenticalObj,
    [ IsFrobeniusAutomorphism, IsFrobeniusAutomorphism ],
    function( aut1, aut2 )
    return Source( aut1 ) = Source( aut2 ) and aut1!.power  = aut2!.power;
    end );

InstallMethod( \=,
    "for identity mapping and Frobenius automorphism",
    IsIdenticalObj,
    [ IsMapping and IsOne, IsFrobeniusAutomorphism ],
    function( id, aut )
    return Source( id ) = Source( aut ) and aut!.power = 1;
    end );

InstallMethod( \=,
    "for Frobenius automorphism and identity mapping",
    IsIdenticalObj,
    [ IsFrobeniusAutomorphism, IsMapping and IsOne ],
    function( aut, id )
    return Source( id ) = Source( aut ) and aut!.power = 1;
    end );

InstallMethod( ImageElm,
    "for Frobenius automorphism and source element",
    FamSourceEqFamElm,
    [ IsFrobeniusAutomorphism, IsObject ],
    function( aut, elm )
    return elm ^ aut!.power;
    end );

InstallMethod( ImagesElm,
    "for Frobenius automorphism and source element",
    FamSourceEqFamElm,
    [ IsFrobeniusAutomorphism, IsObject ],
    function( aut, elm )
    return [ elm ^ aut!.power ];
    end );

InstallMethod( ImagesSet,
    "for Frobenius automorphism and field contained in the source",
    CollFamSourceEqFamElms,
    [ IsFrobeniusAutomorphism, IsField ],
    function( aut, elms )
    return elms;
    end );

InstallMethod( ImagesRepresentative,
    "for Frobenius automorphism and source element",
    FamSourceEqFamElm,
    [ IsFrobeniusAutomorphism, IsObject ],
    function( aut, elm )
    return elm ^ aut!.power;
    end );

InstallMethod( CompositionMapping2,
    "for two Frobenius automorphisms",
    IsIdenticalObj,
    [ IsFrobeniusAutomorphism, IsFrobeniusAutomorphism ],
    function( aut1, aut2 )
    if Characteristic( Source( aut1 ) )
       = Characteristic( Source( aut2 ) ) then
      return FrobeniusAutomorphismI( Source( aut1 ),
                                     aut1!.power * aut2!.power );
    else
      Error( "Frobenius automorphisms of different characteristics" );
    fi;
    end );

InstallMethod( InverseGeneralMapping,
    "for a Frobenius automorphism",
    [ IsFrobeniusAutomorphism ],
    aut -> FrobeniusAutomorphismI( Source( aut ),
                                   Size( Source( aut ) ) / aut!.power ) );

InstallMethod( \^,
    "for a Frobenius automorphism, and an integer",
    [ IsFrobeniusAutomorphism, IsInt ],
    function ( aut, i )
    return FrobeniusAutomorphismI( Source( aut ),
                   PowerModInt( aut!.power, i, Size( Source( aut ) ) - 1 ) );
    end );

InstallMethod( \<,
    "for an identity mapping, and a Frobenius automorphism",
    IsIdenticalObj,
    [ IsMapping and IsOne, IsFrobeniusAutomorphism ],
    function ( id, aut )
    local source1, # source of `id'
          source2, # source of `aut'
          p,       # characteristic
          root,    # primitive root of source
          size,    # size of source
          d,       # degree
          gen;     # generator of cyclic group of subfield

    source1:= Source( id );
    source2:= Source( aut );
    if source1 <> source2 then
      return source1 < source2;
    elif    PrimitiveRoot( source1 )
         <> PrimitiveRoot( source2 ) then
      return   PrimitiveRoot( source1 )
             < PrimitiveRoot( source2 );
#T o.k.?
    else
        p := Characteristic( source1 );
        root:= PrimitiveRoot( source1 );
        size:= Size( source1 );
        for d  in DivisorsInt( LogInt( size, p ) )  do
            gen:= root^( ( size - 1 ) / ( p^d - 1 ) );
            if gen <> gen ^ aut!.power  then
                return gen < gen ^ aut!.power;
            fi;
        od;
        return false;
    fi;
    end );

InstallMethod( \<,
    "for a Frobenius automorphism, and an identity mapping",
    IsIdenticalObj,
    [ IsFrobeniusAutomorphism, IsMapping and IsOne ],
    function ( aut, id )
    local source1, # source of `aut'
          source2, # source of `id'
          p,       # characteristic
          root,    # primitive root of source
          size,    # size of source
          d,       # degree
          gen;     # generator of cyclic group of subfield

    source1:= Source( aut );
    source2:= Source( id );
    if source1 <> source2 then
      return source1 < source2;
    elif    PrimitiveRoot( source1 )
         <> PrimitiveRoot( source2 ) then
      return   PrimitiveRoot( source1 )
             < PrimitiveRoot( source2 );
#T o.k.?
    else
        p := Characteristic( source1 );
        root:= PrimitiveRoot( source1 );
        size:= Size( source1 );
        for d  in DivisorsInt( LogInt( size, p ) )  do
            gen:= root^( ( size - 1 ) / ( p^d - 1 ) );
            if gen ^ aut!.power <> gen then
                return gen ^ aut!.power < gen;
            fi;
        od;
        return false;
    fi;
    end );

InstallMethod( \<,
    "for two Frobenius automorphisms",
    IsIdenticalObj,
    [ IsFrobeniusAutomorphism, IsFrobeniusAutomorphism ],
    function ( aut1, aut2 )
    local source1, # source of `aut1'
          source2, # source of `aut2'
          p,       # characteristic
          root,    # primitive root of source
          size,    # size of source
          d,       # degree
          gen;     # generator of cyclic group of subfield

    source1:= Source( aut1 );
    source2:= Source( aut2 );
    if source1 <> source2 then
      return source1 < source2;
    elif    PrimitiveRoot( source1 )
         <> PrimitiveRoot( source2 ) then
      return   PrimitiveRoot( source1 )
             < PrimitiveRoot( source2 );
#T o.k.?
    else
        p := Characteristic( source1 );
        root:= PrimitiveRoot( source1 );
        size:= Size( source1 );
        for d  in DivisorsInt( LogInt( size, p ) )  do
            gen:= root^( ( size - 1 ) / ( p^d - 1 ) );
            if gen ^ aut1!.power <> gen ^ aut2!.power  then
                return gen ^ aut1!.power < gen ^ aut2!.power;
            fi;
        od;
        return false;
    fi;
    end );

InstallMethod( PrintObj,
    "for a Frobenius automorphism",
    [ IsFrobeniusAutomorphism ],
    function ( aut )
    if aut!.power = Characteristic( Source( aut ) ) then
        Print( "FrobeniusAutomorphism( ", Source( aut ), " )" );
    else
        Print( "FrobeniusAutomorphism( ", Source( aut ), " )^",
               LogInt( aut!.power, Characteristic( Source( aut ) ) ) );
    fi;
    end );


#############################################################################
##
#M  GaloisGroup( <F> )  . . . . . . . . . . .  Galois group of a finite field
##
InstallMethod( GaloisGroup,
    "for a finite field",
    [ IsField and IsFinite ],
    F -> GroupByGenerators(
            [ FrobeniusAutomorphismI( F, Size( LeftActingDomain(F) ) ) ] ) );

[ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge