############################################################################# ## ## This file is part of GAP, a system for computational discrete algebra. ## This file's authors include 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 generic methods for division rings. ##
InstallMethod( DivisionRingByGenerators, "for a division ring, and a collection",
IsIdenticalObj,
[ IsDivisionRing, IsCollection ], function( F, gens )
local D;
D:= Objectify( NewType( FamilyObj( gens ),
IsField and IsAttributeStoringRep ),
rec() );
SetLeftActingDomain( D, F );
SetGeneratorsOfDivisionRing( D, AsList( gens ) );
return D; end );
############################################################################# ## #M FieldOverItselfByGenerators( <gens> ) ##
InstallMethod( FieldOverItselfByGenerators, "for a collection",
[ IsCollection ], function( gens )
local F; if IsEmpty( gens ) then
Error( "need at least one element" ); fi;
F:= Objectify( NewType( FamilyObj( gens ),
IsField and IsAttributeStoringRep ),
rec() );
SetLeftActingDomain( F, F );
SetGeneratorsOfDivisionRing( F, gens );
return F; end );
############################################################################# ## #M DefaultFieldByGenerators( <gens> ) . . . . . . . . . . for a collection ##
InstallMethod( DefaultFieldByGenerators, "for a collection",
[ IsCollection ],
DivisionRingByGenerators );
############################################################################# ## #F Field( <z>, ... ) . . . . . . . . . field generated by a list of elements #F Field( [ <z>, ... ] ) #F Field( <F>, [ <z>, ... ] ) ##
InstallGlobalFunction( Field, function ( arg )
local F; # field containing the elements of <arg>, result
# special case for one square matrix if Length(arg) = 1
and IsMatrix( arg[1] ) and Length( arg[1] ) = Length( arg[1][1] ) then
F := FieldByGenerators( arg );
# special case for list of elements elif Length(arg) = 1 and IsList(arg[1]) then
F := FieldByGenerators( arg[1] );
# special case for subfield and generators elif Length(arg) = 2 and IsField(arg[1]) then
F := FieldByGenerators( arg[1], arg[2] );
# other cases else
F := FieldByGenerators( arg ); fi;
# return the field
return F; end );
############################################################################# ## #F DefaultField( <z>, ... ) . . . . . default field containing a collection ##
InstallGlobalFunction( DefaultField, function ( arg )
local F; # field containing the elements of <arg>, result
# special case for one square matrix if Length(arg) = 1
and IsMatrix( arg[1] ) and Length( arg[1] ) = Length( arg[1][1] ) then
F := DefaultFieldByGenerators( arg );
# special case for list of elements elif Length(arg) = 1 and IsList(arg[1]) then
F := DefaultFieldByGenerators( arg[1] );
# other cases else
F := DefaultFieldByGenerators( arg ); fi;
# return the default field
return F; end );
############################################################################# ## #F Subfield( <F>, <gens> ) . . . . . . . subfield of <F> generated by <gens> #F SubfieldNC( <F>, <gens> ) ##
InstallGlobalFunction( Subfield, function( F, gens )
local S; if IsEmpty( gens ) then
return PrimeField( F ); elif IsHomogeneousList( gens )
and IsIdenticalObj( FamilyObj( F ), FamilyObj( gens ) )
and ForAll( gens, g -> g in F ) then
S:= FieldByGenerators( LeftActingDomain( F ), gens );
SetParent( S, F );
return S; fi;
Error( "<gens> must be a list of elements in <F>" ); end );
InstallGlobalFunction( SubfieldNC, function( F, gens )
local S; if IsEmpty( gens ) then
S:= Objectify( NewType( FamilyObj( F ),
IsDivisionRing and IsAttributeStoringRep ),
rec() );
SetLeftActingDomain( S, F );
SetGeneratorsOfDivisionRing( S, AsList( gens ) ); else
S:= DivisionRingByGenerators( LeftActingDomain( F ), gens ); fi;
SetParent( S, F );
return S; end );
############################################################################# ## #M ClosureDivisionRing( <D>, <d> ) . . . . . . . . . closure with an element ##
InstallMethod( ClosureDivisionRing, "for a division ring and a scalar",
IsCollsElms,
[ IsDivisionRing, IsScalar ], function( D, d )
# if possible test if the element lies in the division ring already, if HasGeneratorsOfDivisionRing( D )
and d in GeneratorsOfDivisionRing( D ) then
return D;
# otherwise make a new division ring else
return DivisionRingByGenerators( LeftActingDomain( D ),
Concatenation( GeneratorsOfDivisionRing( D ), [ d ] ) ); fi; end );
InstallMethod( ClosureDivisionRing, "for a division ring containing the whole family, and a scalar",
IsCollsElms,
[ IsDivisionRing and IsWholeFamily, IsScalar ],
SUM_FLAGS, # we can't be better than this
ReturnFirst);
############################################################################# ## #M ClosureDivisionRing( <D>, <C> ) . . . . . . . . closure of division ring ##
InstallMethod( ClosureDivisionRing, "for division ring and collection of elements",
IsIdenticalObj,
[ IsDivisionRing, IsCollection ], function( D, C )
local d; # one generator
if IsDivisionRing( C ) then if not IsSubset( LeftActingDomain( D ), LeftActingDomain( C ) ) then
C:= AsDivisionRing( Intersection( LeftActingDomain( C ),
LeftActingDomain( D ) ), C ); fi;
C:= GeneratorsOfDivisionRing( C ); elif not IsList( C ) then
TryNextMethod(); fi;
for d in C do
D:= ClosureDivisionRing( D, d );
od;
return D; end );
InstallMethod( ClosureDivisionRing, "for division ring and empty list",
[ IsDivisionRing, IsList and IsEmpty ],
ReturnFirst);
############################################################################# ## #M ViewObj( <F> ) . . . . . . . . . . . . . . . . . . . . . . view a field ##
InstallMethod( ViewObj, "for a field",
[ IsField ], function( F ) if HasSize( F ) and IsInt( Size( F ) ) then
Print( "<field of size ", String(Size( F )), ">" ); else
Print( "<field in characteristic ", Characteristic( F ), ">" ); fi; end );
############################################################################# ## #M ViewString( <F> ) . . . . . . . . . . . . . . . . . . . . . view a field ##
InstallMethod( ViewString, "for a field",
[ IsField ], function( F ) if HasSize( F ) and IsInt( Size( F ) ) then
return Concatenation("<field of size ", String(Size( F )), ">" ); else
return Concatenation( "<field in characteristic ",
String(Characteristic( F )), ">" ); fi; end );
############################################################################# ## #M PrintObj( <F> ) . . . . . . . . . . . . . . . . . . . . . . print a field ##
InstallMethod( PrintObj, "for a field with known generators",
[ IsField and HasGeneratorsOfField ], function( F ) if IsIdenticalObj(F,LeftActingDomain(F)) or
IsPrimeField( LeftActingDomain( F ) ) then
Print( "Field( ", GeneratorsOfField( F ), " )" ); elif F = LeftActingDomain( F ) then
Print( "FieldOverItselfByGenerators( ",
GeneratorsOfField( F ), " )" ); else
Print( "AsField( ", LeftActingDomain( F ), ", Field( ", GeneratorsOfField( F ), " ) )" ); fi; end );
InstallMethod( PrintObj, "for a field",
[ IsField ], function( F ) if IsPrimeField( LeftActingDomain( F ) ) then
Print( "Field( ... )" ); elif F = LeftActingDomain( F ) then
Print( "AsField( ~, ... )" ); else
Print( "AsField( ", LeftActingDomain( F ), ", ... )" ); fi; end );
############################################################################# ## #M IsTrivial( <F> ) . . . . . . . . . . . . . . . . . . for a division ring ##
InstallMethod( IsTrivial, "for a division ring",
[ IsDivisionRing ],
ReturnFalse );
############################################################################# ## #M PrimeField( <F> ) . . . . . . . . . . . . . . . . . . for a division ring ##
InstallMethod( PrimeField, "for a division ring",
[ IsDivisionRing ], function( F )
local P;
P:= Field( One( F ) );
UseSubsetRelation( F, P );
SetIsPrimeField( P, true );
return P; end );
InstallMethod( PrimeField, "for a prime field",
[ IsField and IsPrimeField ],
IdFunc );
############################################################################# ## #M IsPrimeField( <F> ) . . . . . . . . . . . . . . . . . for a division ring ##
InstallMethod( IsPrimeField, "for a division ring",
[ IsDivisionRing ],
F -> DegreeOverPrimeField( F ) = 1 );
############################################################################# ## #M IsNumberField( <F> ) . . . . . . . . . . . . . . . . . . . . for a field ##
InstallMethod( IsNumberField, "for a field",
[ IsField ],
F -> Characteristic( F ) = 0 and IsInt( DegreeOverPrimeField( F ) ) );
############################################################################# ## #M IsAbelianNumberField( <F> ) . . . . . . . . . . . . . . . . . for a field ##
InstallMethod( IsAbelianNumberField, "for a field",
[ IsField ],
F -> IsNumberField( F ) and IsCommutative( GaloisGroup(
AsField( PrimeField( F ), F ) ) ) );
############################################################################# ## #M IsCyclotomicField( <F> ) . . . . . . . . . . . . . . . . . . for a field ##
InstallMethod( IsCyclotomicField, "for a field",
[ IsField ],
F -> IsAbelianNumberField( F )
and Conductor( F ) = DegreeOverPrimeField( F ) );
############################################################################# ## #M IsNormalBasis( <B> ) . . . . . . . . . . . . . for a basis (of a field) ##
InstallMethod( IsNormalBasis, "for a basis of a field",
[ IsBasis ], function( B )
local vectors; if not IsField( UnderlyingLeftModule( B ) ) then
Error( "<B> must be a basis of a field" ); fi;
vectors:= BasisVectors( B );
return Set( vectors )
= Set( Conjugates( UnderlyingLeftModule( B ), vectors[1] ) ); end );
############################################################################# ## #M GeneratorsOfDivisionRing( <F> ) . . . . . . . . . . . . for a prime field ##
InstallMethod( GeneratorsOfDivisionRing, "for a prime field",
[ IsField and IsPrimeField ],
F -> [ One( F ) ] );
############################################################################# ## #M DegreeOverPrimeField( <F> ) . . . . . . . . . . . . . . for a prime field ##
InstallImmediateMethod( DegreeOverPrimeField, IsPrimeField, 20, F -> 1 );
############################################################################# ## #M NormalBase( <F> ) . . . . . . . . . . for a field in characteristic zero #M NormalBase( <F>, <elm> ) . . . . . . for a field in characteristic zero ## ## For fields in characteristic zero, a normal basis is computed ## as described on p.~65~f.~in~\cite{Art68}. ## Let $\Phi$ denote the polynomial of the field extension $L/L^{\prime}$, ## $\Phi^{\prime}$ its derivative and $\alpha$ one of its roots; ## then for all except finitely many elements $z \in L^{\prime}$, ## the conjugates of $\frac{\Phi(z)}{(z-\alpha)\cdot\Phi^{\prime}(\alpha)}$ ## form a normal basis of $L/L^{\prime}$. ## ## When `NormalBase' is called for a field <F> in characteristic zero and ## an element <elm>, ## $z$ is chosen as <elm>, $<elm> + 1$, $<elm> + 2$, \ldots, ## until a normal basis is found. ## The default of <elm> is the identity of <F>. ##
InstallMethod( NormalBase, "for a field (in characteristic zero)",
[ IsField ],
F -> NormalBase( F, One( F ) ) );
InstallMethod( NormalBase, "for a field (in characteristic zero), and a scalar",
[ IsField, IsScalar ], function( F, z )
local alpha, poly, i, val, normal;
# Check the arguments. if Characteristic( F ) <> 0then
TryNextMethod(); elif not z in F then
Error( "<z> must be an element in <F>" ); fi;
# Get a primitive element `alpha'.
alpha:= PrimitiveElement( F );
# Construct the polynomial # $\prod_{\sigma\in `Gal( alpha )'\setminus \{1\} } (x-\sigma(`alpha') ) # for the primitive element `alpha'.
poly:= [ 1 ]; for i in Difference( Conjugates( F, alpha ), [ alpha ] ) do
poly:= ProductCoeffs( poly, [ -i, 1 ] ); #T ?
od;
# For the denominator, evaluate `poly' at `a'.
val:= Inverse( ValuePol( poly, alpha ) );
# There are only finitely many values `x' in the subfield # for which `poly(x) * val' is not an element of a normal basis.
repeat
normal:= Conjugates( F, ValuePol( poly, z ) * val );
z:= z + 1;
until RankMat( List( normal, COEFFS_CYC ) ) = Dimension( F );
# Return the result.
return normal; end );
############################################################################# ## #M PrimitiveElement( <D> ) . . . . . . . . . . . . . . . for a division ring ##
InstallMethod( PrimitiveElement, "for a division ring",
[ IsDivisionRing ], function( D )
D:= GeneratorsOfDivisionRing( D ); if Length( D ) = 1then
return D[1]; else
TryNextMethod(); fi; end );
############################################################################# ## #M Representative( <D> ) . . . . . for a division ring with known generators ##
InstallMethod( Representative, "for a division ring with known generators",
[ IsDivisionRing and HasGeneratorsOfDivisionRing ],
RepresentativeFromGenerators( GeneratorsOfDivisionRing ) );
############################################################################# ## #M Enumerator( <F> ) . . . . . . . . . . elements of a (finite) prime field #M EnumeratorSorted( <F> ) . . . . . . . elements of a (finite) prime field ## ## We install a special method only for (finite) prime fields, ## since the other cases are handled by the vector space methods. ##
BindGlobal( "EnumeratorOfPrimeField", function( F )
local one;
one:= One( F ); if Size( F ) <= MAXSIZE_GF_INTERNAL then
return AsSSortedListList( List( [ 0 .. Size( F ) - 1 ], i -> i * one ) ); elif IsZmodnZObj( one ) then
return EnumeratorOfZmodnZ( F ); fi;
TryNextMethod(); end );
InstallMethod( Enumerator, "for a finite prime field",
[ IsField and IsPrimeField and IsFinite ],
EnumeratorOfPrimeField );
InstallMethod( EnumeratorSorted, "for a finite prime field",
[ IsField and IsPrimeField and IsFinite ],
EnumeratorOfPrimeField );
InstallMethod( AsList, "for a finite prime field",
[ IsField and IsPrimeField and IsFinite ],
F -> AsList( Enumerator( F ) ) );
############################################################################# ## #M IsSubset( <D>, <F> ) . . . . . . . . . . . . . . for two division rings ## ## We have to be careful not to run into an infinite recursion in the case ## that <F> is equal to its left acting domain. ## Also we must be aware of situations where the left acting domains are ## in a family different from that of the fields themselves, ## for example <D> could be given as a field over a field that is really ## a subset of <D>, whereas the left acting domain of <F> is not a subset ## of <F>. ##
BindGlobal( "DivisionRing_IsSubset", function( D, F )
local CF;
# Special case for when F equals the cyclotomics (and hence is infinite # dimensional over its left acting domain). if IsIdenticalObj(F, Cyclotomics) then
return IsIdenticalObj(D, Cyclotomics); fi;
CF:= LeftActingDomain( F );
if not IsSubset( D, GeneratorsOfDivisionRing( F ) ) then
return false; elif IsSubset( LeftActingDomain( D ), CF ) or IsPrimeField( CF ) then
return true; elif FamilyObj( F ) = FamilyObj( CF ) then
return IsSubset( D, CF ); else
CF:= AsDivisionRing( PrimeField( CF ), CF );
return IsSubset( D, List( GeneratorsOfDivisionRing( CF ),
x -> x * One( F ) ) ); fi; end );
############################################################################# ## #M \=( <D>, <F> ) . . . . . . . . . . . . . . . . . for two division rings ##
InstallMethod( \=, "for two division rings",
IsIdenticalObj,
[ IsDivisionRing, IsDivisionRing ], function( D, F )
return DivisionRing_IsSubset( D, F ) and DivisionRing_IsSubset( F, D ); end );
############################################################################# ## #M AsDivisionRing( <C> ) . . . . . . . . . . . . . . . . . for a collection ##
InstallMethod( AsDivisionRing, "for a collection",
[ IsCollection ], function( C )
local one, F;
# A division ring contains at least two elements. if IsEmpty( C ) or IsTrivial( C ) then
return fail; fi;
# Construct the prime field.
one:= One( Representative( C ) ); if one = fail then
return fail; fi;
F:= FieldOverItselfByGenerators( [ one ] );
# Delegate to the two-argument version.
return AsDivisionRing( F, C ); end );
############################################################################# ## #M AsDivisionRing( <F>, <C> ) . . . . for a division ring, and a collection ##
InstallMethod( AsDivisionRing, "for a division ring, and a collection",
IsIdenticalObj,
[ IsDivisionRing, IsCollection ], function( F, C )
local D;
if not IsSubset( C, F ) then
return fail; fi;
D:= DivisionRingByGenerators( F, C ); if D <> C then
return fail; fi;
return D; end );
############################################################################# ## #M AsDivisionRing( <F>, <D> ) . . . . . . . . . . . for two division rings ##
InstallMethod( AsDivisionRing, "for two division rings",
IsIdenticalObj,
[ IsDivisionRing, IsDivisionRing ], function( F, D )
local E;
if F = LeftActingDomain( D ) then
return D; elif not IsSubset( D, F ) then
return fail; fi;
E:= DivisionRingByGenerators( F, GeneratorsOfDivisionRing( D ) );
UseIsomorphismRelation( D, E );
UseSubsetRelation( D, E );
return E; end );
############################################################################# ## #M AsLeftModule( <F1>, <F2> ) . . . . . . . . . . . for two division rings ## ## View the division ring <F2> as vector space over the division ring <F1>. ##
InstallMethod( AsLeftModule, "for two division rings",
IsIdenticalObj,
[ IsDivisionRing, IsDivisionRing ],
AsDivisionRing );
############################################################################# ## #M Conjugates( <F>, <z> ) . . . . . . . . . . conjugates of a field element #M Conjugates( <z> ) . . . . . . . . . . . . . conjugates of a field element ##
InstallMethod( Conjugates, "for a scalar (delegate to version with default field)",
[ IsScalar ],
z -> Conjugates( DefaultField( z ), z ) );
InstallMethod( Conjugates, "for a field and a scalar (delegate to version with two fields)",
IsCollsElms,
[ IsField, IsScalar ], function( F, z )
return Conjugates( F, LeftActingDomain( F ), z ); end );
############################################################################# ## #M Conjugates( <L>, <K>, <z> ) . . for a field elm. (use `TracePolynomial') ##
InstallMethod( Conjugates, "for two fields and a scalar (call `TracePolynomial')",
IsCollsXElms,
[ IsField, IsField, IsScalar ], function( L, K, z )
local pol, lin, conj, mult, i;
# Check whether `Conjugates' is allowed to call `MinimalPolynomial'. if IsFieldControlledByGaloisGroup( L ) then
TryNextMethod(); fi;
# Compute the roots in `L' of the minimal polynomial of `z' over `K'.
pol:= MinimalPolynomial( K, z );
lin:= List( Filtered( Factors( L, pol ),
x -> DegreeOfLaurentPolynomial( x ) = 1 ),
CoefficientsOfUnivariatePolynomial );
lin:= List( lin, x -> AdditiveInverse( lin[1] / lin[2] ) );
# Take the roots with the appropriate multiplicity.
conj:= [];
mult:= DegreeOverPrimeField( L ) / DegreeOverPrimeField( K );
mult:= mult / DegreeOfLaurentPolynomial( pol ); for i in [ 1 .. mult ] do
Append( conj, lin );
od;
return conj; end );
############################################################################# ## #M Conjugates( <L>, <K>, <z> ) . . . for a field element (use `GaloisGroup') ##
InstallMethod( Conjugates, "for two fields and a scalar (call `GaloisGroup')",
IsCollsXElms,
[ IsFieldControlledByGaloisGroup, IsField, IsScalar ], function( L, K, z )
local cnjs, # conjugates of <z> in <F>, result
aut; # automorphism of <F>
# Check the arguments. if not z in L then
Error( "<z> must lie in <L>" ); fi;
# Compute the conjugates simply by applying all the automorphisms.
cnjs:= []; for aut in GaloisGroup( AsField( L, K ) ) do
Add( cnjs, z ^ aut );
od;
# Return the conjugates.
return cnjs; end );
############################################################################# ## #M Norm( <F>, <z> ) . . . . . . . . . . . . . . . . norm of a field element #M Norm( <z> ) . . . . . . . . . . . . . . . . . . . norm of a field element ##
InstallMethod( Norm, "for a scalar (delegate to version with default field)",
[ IsScalar ],
z -> Norm( DefaultField( z ), z ) );
InstallMethod( Norm, "for a field and a scalar (delegate to version with two fields)",
IsCollsElms,
[ IsField, IsScalar ], function( F, z )
return Norm( F, LeftActingDomain( F ), z ); end );
############################################################################# ## #M Norm( <L>, <K>, <z> ) . . . . norm of a field element (use `Conjugates') ##
InstallMethod( Norm, "for two fields and a scalar (use `Conjugates')",
IsCollsXElms,
[ IsFieldControlledByGaloisGroup, IsField, IsScalar ], function( L, K, z )
return Product( Conjugates( L, K, z ) ); end );
############################################################################# ## #M Norm( <L>, <K>, <z> ) . . . norm of a field element (use the trace pol.) ##
InstallMethod( Norm, "for two fields and a scalar (use the trace pol.)",
IsCollsXElms,
[ IsField, IsField, IsScalar ], function( L, K, z )
local coeffs;
coeffs:= CoefficientsOfUnivariatePolynomial(
TracePolynomial( L, K, z, 1 ) );
return (-1)^(Length( coeffs )-1) * coeffs[1]; end );
############################################################################# ## #M Trace( <z> ) . . . . . . . . . . . . . . . . . trace of a field element #M Trace( <F>, <z> ) . . . . . . . . . . . . . . . trace of a field element ##
InstallMethod( Trace, "for a scalar (delegate to version with default field)",
[ IsScalar ],
z -> Trace( DefaultField( z ), z ) );
InstallMethod( Trace, "for a field and a scalar (delegate to version with two fields)",
IsCollsElms,
[ IsField, IsScalar ], function( F, z )
return Trace( F, LeftActingDomain( F ), z ); end );
############################################################################# ## #M Trace( <L>, <K>, <z> ) . . . trace of a field element (use `Conjugates') ##
InstallMethod( Trace, "for two fields and a scalar (use `Conjugates')",
IsCollsXElms,
[ IsFieldControlledByGaloisGroup, IsField, IsScalar ], function( L, K, z )
return Sum( Conjugates( L, K, z ) ); end );
############################################################################# ## #M Trace( <L>, <K>, <z> ) . . trace of a field element (use the trace pol.) ##
InstallMethod( Trace, "for two fields and a scalar (use the trace pol.)",
IsCollsXElms,
[ IsField, IsField, IsScalar ], function( L, K, z )
local coeffs;
coeffs:= CoefficientsOfUnivariatePolynomial(
TracePolynomial( L, K, z, 1 ) );
return AdditiveInverse( coeffs[ Length( coeffs ) - 1 ] ); end );
############################################################################# ## #M MinimalPolynomial( <F>, <z>, <nr> ) ## ## If the default field of <z> knows how to get the Galois group then ## we compute the conjugates and from them the minimal polynomial. ## Otherwise we solve an equation system. ## ## Note that the family predicate `IsCollsElmsX' expresses that <z> may lie ## in an extension field of <F>; ## this guarantees that the method is *not* applicable for the case that <z> ## is a matrix. ##
InstallMethod( MinimalPolynomial, "for field, scalar, and indet. number",
IsCollsElmsX,
[ IsField, IsScalar,IsPosInt ], function( F, z, ind )
local L, coe, deg, zero, con, i, B, pow, mat, MB;
# Construct a basis of a field in which the computations happen. # (This need not be the smallest such field.)
L:= DefaultField( z );
if IsFieldControlledByGaloisGroup( L ) then
# We may call `Conjugates'.
coe:= [ One( F ) ];
deg:= 0;
zero:= Zero( F ); for con in Conjugates( Field( F, [ z ] ), z ) do
coe[deg+2]:= coe[deg+1]; for i in [ deg+1, deg .. 2 ] do
coe[i]:= coe[i-1] - con * coe[i];
od;
coe[1]:= zero - con * coe[1];
deg:= deg + 1;
od;
else
# Solve an equation system.
B:= Basis( L );
# Compute coefficients of the powers of `z' until # the rows are linearly dependent.
pow:= One( F );
coe:= Coefficients( B, pow );
mat:= [ coe ];
MB:= MutableBasis( F, [ coe ] );
repeat
CloseMutableBasis( MB, coe );
pow:= pow * z;
coe:= Coefficients( B, pow );
Add( mat, coe );
until IsContainedInSpan( MB, coe );
# The coefficients of the minimal polynomial # are given by the linear relation.
coe:= NullspaceMat( mat )[1];
coe:= Inverse( Last(coe) ) * coe;
fi;
# Construct the polynomial.
return UnivariatePolynomial( F, coe, ind ); end );
minpol:= MinimalPolynomial( K, z, ind );
mult:= DegreeOverPrimeField( L ) / DegreeOverPrimeField( K );
mult:= mult / DegreeOfLaurentPolynomial( minpol );
############################################################################# ## #M NiceFreeLeftModuleInfo( <V> ) #M NiceVector( <V>, <v> ) #M UglyVector( <V>, <r> ) ##
InstallHandlingByNiceBasis( "IsFieldElementsSpace", rec(
detect := function( F, gens, V, zero )
return IsScalarCollection( V )
and IsIdenticalObj( FamilyObj( F ), FamilyObj( V ) )
and IsDivisionRing( F ); end,
NiceFreeLeftModuleInfo := function( V )
local lad, gens;
# Compute the default field of the vector space generators, # and a basis of this field (over the left acting domain of `V').
lad:= LeftActingDomain( V ); if not IsIdenticalObj( FamilyObj( V ), FamilyObj( lad ) ) then
TryNextMethod(); fi;
return Basis( AsField( lad,
ClosureField( lad, GeneratorsOfLeftModule( V ) ) ) ); end,
NiceVector := function( V, v )
return Coefficients( NiceFreeLeftModuleInfo( V ), v ); end,
UglyVector := function( V, r )
local B;
B:= NiceFreeLeftModuleInfo( V ); if Length( r ) <> Length( B ) then
return fail; fi;
return LinearCombination( B, r ); end ) );
############################################################################# ## #M Quotient( <F>, <r>, <s> ) . . . . . . . . quotient of elements in a field ##
InstallMethod( Quotient, "for a division ring, and two ring elements",
IsCollsElmsElms,
[ IsDivisionRing, IsRingElement, IsRingElement ], function ( F, r, s ) if IsZero(s) then
return fail; fi;
return r/s; end );
############################################################################# ## #M IsUnit( <F>, <r> ) . . . . . . . . . . check for being a unit in a field ##
InstallMethod( IsUnit, "for a division ring, and a ring element",
IsCollsElms,
[ IsDivisionRing, IsRingElement ], function ( F, r )
return not IsZero( r ) and r in F; end );
############################################################################# ## #M Units( <F> ) ##
InstallMethod( Units, "for a division ring",
[ IsDivisionRing ], function( D ) if IsFinite( D ) then
return Difference( AsList( D ), [ Zero( D ) ] ); else
TryNextMethod(); fi; end );
############################################################################# ## #M PrimitiveRoot( <F> ) . . . . . . . . . . . . for finite prime field <F> ## ## For a fields of prime order $p$, the multiplicative group corresponds to ## the group of residues modulo $p$, via `Int'. ## A primitive root is obtained as `PrimitiveRootMod( $p$ )' times the ## identity of <F>. ##
InstallMethod( PrimitiveRoot, "for a finite prime field",
[ IsField and IsFinite ], function( F ) if not IsPrimeField( F ) then
TryNextMethod(); fi;
return PrimitiveRootMod( Size( F ) ) * One( F ); end );
############################################################################# ## #M EuclideanDegree( Integers, <n> ) . . . . . . . . . . . . . absolute value ##
InstallMethod( EuclideanDegree, "for a division ring and a ring element",
IsCollsElms,
[ IsDivisionRing, IsRingElement ], function ( F, r ) if not r in F then
TryNextMethod(); # FIXME: or error? fi;
return 0; end );
############################################################################# ## #M QuotientRemainder( Integers, <n>, <m> ) . . . . . . . . . . . quo and rem ##
InstallMethod( QuotientRemainder, "for a division ring, and two ring elements",
IsCollsElmsElms,
[ IsDivisionRing, IsRingElement, IsRingElement ], function ( F, r, s ) if not r in F then
TryNextMethod(); # FIXME: or error? fi;
return [ r/s, Zero(F) ]; end );
############################################################################# ## #M Factors( Integers, <n> ) . . . . . . . . . . factorization of an integer ##
InstallMethod( Factors, "for a division ring and a ring element",
IsCollsElms,
[ IsDivisionRing, IsRingElement ], function ( F, r ) if not r in F then
TryNextMethod(); # FIXME: or error? fi;
return [ r ]; end );
############################################################################# ## #M IsAssociated( <F>, <r>, <s> ) . . . . . . check associatedness in a field ##
InstallMethod( IsAssociated, "for a division ring, and two ring elements",
IsCollsElmsElms,
[ IsDivisionRing, IsRingElement, IsRingElement ], function ( F, r, s )
return IsZero( r ) = IsZero( s ); end );
############################################################################# ## #M StandardAssociate( <F>, <x> ) . . . . . . . standard associate in a field ##
InstallMethod( StandardAssociate, "for a division ring and a ring element",
IsCollsElms,
[ IsDivisionRing, IsScalar ], function ( R, r ) if IsZero( r ) then
return Zero( R ); else
return One( R ); fi; end );
############################################################################# ## #M StandardAssociateUnit( <F>, <x> ) ##
InstallMethod( StandardAssociateUnit, "for a division ring and a ring element",
IsCollsElms,
[ IsDivisionRing, IsScalar ], function ( R, r ) if IsZero( r ) then
return One( R ); else
return r^-1; fi; end );
############################################################################# ## #M IsIrreducibleRingElement( <F>, <x> ) ##
InstallMethod(IsIrreducibleRingElement, "for a division ring and a ring element",
IsCollsElms,
[ IsDivisionRing, IsScalar ], function ( F, r ) if not r in F then
TryNextMethod(); # FIXME: or error? fi; # field elements are either zero or a unit
return false; end );
############################################################################# ## #M IsPrime( <F>, <x> ) ##
InstallMethod(IsPrime, "for a division ring and a ring element",
IsCollsElms,
[ IsDivisionRing, IsScalar ], function ( F, r ) if not r in F then
TryNextMethod(); # FIXME: or error? fi; # field elements are either zero or a unit
return false; end );
############################################################################# ## ## Field homomorphisms ##
############################################################################# ## #M KernelOfAdditiveGeneralMapping( <fldhom> ) . . for a field homomorphism ##
InstallMethod( KernelOfAdditiveGeneralMapping, "for a field homomorphism",
[ IsFieldHomomorphism ], #T higher rank? #T (is this method ever used?) function ( hom ) if ForAll( GeneratorsOfDivisionRing( Source( hom ) ),
x -> IsZero( ImagesRepresentative( hom, x ) ) ) then
return Source( hom ); else
return TrivialSubadditiveMagmaWithZero( Source( hom ) ); fi; end );
############################################################################# ## #M IsInjective( <fldhom> ) . . . . . . . . . . . . for a field homomorphism ##
InstallMethod( IsInjective, "for a field homomorphism",
[ IsFieldHomomorphism ],
hom -> Size( KernelOfAdditiveGeneralMapping( hom ) ) = 1 );
############################################################################# ## #M IsSurjective( <fldhom> ) . . . . . . . . . . . for a field homomorphism ##
InstallMethod( IsSurjective, "for a field homomorphism",
[ IsFieldHomomorphism ], function ( hom ) if IsFinite( Range( hom ) ) then
return Size( Range( hom ) ) = Size( Image( hom ) ); else
TryNextMethod(); fi; end );
############################################################################# ## #M \=( <hom1>, <hom2> ) . . . . . . . . . comparison of field homomorphisms ##
InstallMethod( \=, "for two field homomorphisms",
IsIdenticalObj,
[ IsFieldHomomorphism, IsFieldHomomorphism ], function ( hom1, hom2 )
# maybe the properties we already know determine the result if ( HasIsInjective( hom1 ) and HasIsInjective( hom2 )
and IsInjective( hom1 ) <> IsInjective( hom2 ) )
or ( HasIsSurjective( hom1 ) and HasIsSurjective( hom2 )
and IsSurjective( hom1 ) <> IsSurjective( hom2 ) ) then
return false;
# otherwise we must really test the equality else
return Source( hom1 ) = Source( hom2 )
and Range( hom1 ) = Range( hom2 )
and ForAll( GeneratorsOfField( Source( hom1 ) ),
elm -> Image(hom1,elm) = Image(hom2,elm) ); fi; end );
############################################################################# ## #M ImagesSet( <hom>, <elms> ) . . images of a set under a field homomorphism ##
InstallMethod( ImagesSet, "for field homomorphism and field",
CollFamSourceEqFamElms,
[ IsFieldHomomorphism, IsField ], function ( hom, elms )
elms:= FieldByGenerators( List( GeneratorsOfField( elms ),
gen -> ImagesRepresentative( hom, gen ) ) );
UseSubsetRelation( Range( hom ), elms );
return elms; end );
############################################################################# ## #M PreImagesElm( <hom>, <elm> ) . . . . . . . . . . . . preimage of an elm ##
InstallMethod( PreImagesElm, "for field homomorphism and element",
FamRangeEqFamElm,
[ IsFieldHomomorphism, IsObject ], function ( hom, elm ) if IsInjective( hom ) = 1then
return [ PreImagesRepresentative( hom, elm ) ]; elif IsZero( elm ) then
return Source( hom ); else
return []; fi; end );
############################################################################# ## #M PreImagesSet( <hom>, <elm> ) . . . . . . . . . . . . . preimage of a set ##
InstallMethod( PreImagesSet, "for field homomorphism and field",
CollFamRangeEqFamElms,
[ IsFieldHomomorphism, IsField ], function ( hom, elms )
elms:= FieldByGenerators( List( GeneratorsOfField( elms ),
gen -> PreImagesRepresentative( hom, gen ) ) );
UseSubsetRelation( Source( hom ), elms );
return elms; end );
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.27 Sekunden
(vorverarbeitet am 2026-10-12)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.