home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-05-05 | 30.5 KB | 1,088 lines |
- #############################################################################
- ##
- #A field.g GAP library Martin Schoenert
- ##
- #A @(#)$Id: field.g,v 3.9 1993/01/20 11:14:52 fceller Rel $
- ##
- #Y Copyright 1990-1992, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany
- ##
- ## This file contains those functions that are dispatcher for fields.
- ##
- #H $Log: field.g,v $
- #H Revision 3.9 1993/01/20 11:14:52 fceller
- #H added generic 'Polynomial' and 'PolynomialRing'
- #H
- #H Revision 3.8 1992/12/16 19:47:27 martin
- #H replaced quoted record names with escaped ones
- #H
- #H Revision 3.7 1992/11/16 12:22:40 fceller
- #H added Laurent polynomials
- #H
- #H Revision 3.6 1992/08/13 13:11:09 fceller
- #H add 'Indeterminate'
- #H
- #H Revision 3.5 1992/04/05 14:50:49 martin
- #H changed 'Field' slightly
- #H
- #H Revision 3.4 1992/03/27 11:14:51 martin
- #H changed mapping to general mapping and function to mapping
- #H
- #H Revision 3.3 1992/02/11 14:16:36 martin
- #H added 'GaloisGroup'
- #H
- #H Revision 3.2 1991/12/04 09:07:01 martin
- #H changed 'Field' and 'DefaultField' to use 'Domain', removed 'FieldDomain'
- #H
- #H Revision 3.1 1991/10/10 12:38:50 martin
- #H changed everything for new domain concept
- #H
- #H Revision 3.0 1991/08/08 15:30:29 martin
- #H initial revision under RCS
- #H
- ##
-
-
- #############################################################################
- ##
- #F IsField(<D>) . . . . . . . . . . . . . . . . test if a domain is a field
- ##
- IsField := function ( D )
- return IsRec( D ) and IsBound( D.isField ) and D.isField;
- end;
-
-
- #############################################################################
- ##
- #V FieldOps . . . . . . . . . . . . . . . . . . operations record for field
- ##
- ## 'FieldOps' is the operations record for fields.
- ##
- ## The operations records for special fields are created by making a copy of
- ## this record and overlaying some functions. This way those fields inherit
- ## the default methods.
- ##
- FieldOps := Copy( DomainOps );
-
-
- #############################################################################
- ##
- #F FieldOps.\=( <F>, <G> ) . . . . . . . . . . . . . comparisons of fields
- ##
- FieldOps.\= := function ( F, G )
- local isEql;
- if IsField( F ) and IsFinite( F ) then
- if IsField( G ) and IsFinite( G ) then
- isEql := ( Size( F ) = Size( G ) )
- and ForAll( F.generators, g -> g in G )
- and ForAll( G.generators, g -> g in F );
- elif IsField( G ) then
- isEql := false;
- else
- isEql := DomainOps.\=( F, G );
- fi;
- elif IsField( F ) then
- if IsField( G ) and IsFinite( G ) then
- isEql := false;
- elif IsField( G ) then
- isEql := ForAll( F.generators, g -> g in G )
- and ForAll( G.generators, g -> g in F );
- else
- isEql := DomainOps.\=( F, G );
- fi;
- else
- isEql := DomainOps.\=( F, G );
- fi;
- return isEql;
- end;
-
-
- #############################################################################
- ##
- #F FieldOps.IsSubset(<F>,<G>) . . test if something is a subset of a field
- ##
- FieldOps.IsSubset := function ( F, G )
- local isSub;
- if IsField( F ) and IsFinite( F ) then
- if IsField( G ) and IsFinite( G ) then
- isSub := Size( F ) mod Size( G ) = 0
- and (Size( F ) - 1) mod (Size( G ) - 1) = 0
- and ForAll( G.generators, g -> g in F );
- elif IsField( G ) then
- isSub := false;
- else
- isSub := DomainOps.\=( F, G );
- fi;
- elif IsField( F ) then
- if IsField( G ) then
- isSub := ForAll( G.generators, g -> g in F );
- else
- isSub := DomainOps.\=( F, G );
- fi;
- else
- isSub := DomainOps.\=( F, G );
- fi;
- return isSub;
- end;
-
-
- #############################################################################
- ##
- #F FieldOps.Print( <F> ) . . . . . . . . . . . . . . . . . . . print a field
- ##
- FieldOps.Print := function ( F )
- local i;
- if IsBound( F.name ) then
- Print( F.name );
- else
- Print( "Field( ");
- for i in [1..Length(F.generators)-1] do
- Print( F.generators[i], ", " );
- od;
- Print( F.generators[Length(F.generators)], " )" );
- if IsBound( F.field ) then
- Print( "/", F.field );
- fi;
- fi;
- end;
-
-
- #############################################################################
- ##
- #F FieldOps.\/( <F>, <G> ) . . . . . . . . . . . . quotient of two fields
- ##
- FieldOps.\/ := function ( F, G )
- local Q;
-
- # check the arguments
- if IsField(F) and IsField(G) and IsSubset(F,G) then
-
- # make the domain
- Q := rec();
- Q.isDomain := true;
- Q.isField := true;
-
- # enter the identification
- Q.char := F.char;
- Q.degree := F.degree;
- Q.generators := F.generators;
- Q.zero := F.zero;
- Q.one := F.one;
-
- # enter the knowledge
- Q.size := F.size;
- Q.isFinite := F.isFinite;
-
- # enter the subfield
- Q.field := G;
- Q.dimension := F.degree / G.degree;
-
- # and finally the operations record
- Q.operations := F.operations;
-
- else
- Error("<G> must be a subfield of <F>");
- fi;
-
- # return the quotient
- return Q;
- end;
-
-
- #############################################################################
- ##
- #F FieldOps.\^( <F>, <n> ) . . . . . . . . . . . . row space over a field
- ##
- FieldOps.\^ := function ( F, n )
- local V;
- if IsField(F) and IsInt(n) and 0 <= n then
- V := RowSpace( n, F );
- else
- Error("power of <F> and <n> is not defined");
- fi;
- return V;
- end;
-
-
- #############################################################################
- ##
- #F GaloisGroup( <F> ) . . . . . . . . . . . . . . . Galois group of a field
- ##
- GaloisGroup := function ( F )
-
- # check the argument
- if not IsField( F ) then
- Error("<F> must be a field");
- fi;
-
- # compute the Galois group
- if not IsBound( F.galoisGroup ) then
- F.galoisGroup := F.operations.GaloisGroup( F );
- fi;
-
- # return the Galois group
- return F.galoisGroup;
- end;
-
- FieldOps.GaloisGroup := function ( F )
- Error("sorry, no generic method to compute the Galois group");
- end;
-
- FieldOps.AutomorphismGroup := function ( F )
- return GaloisGroup( F );
- end;
-
-
- #############################################################################
- ##
- #F Conjugates([<F>,]<z>) . . . . . . . . . . . conjugates of a field element
- ##
- Conjugates := function ( arg )
- local F, # field <F>, optional first argument
- z; # element <z>, second argument
-
- # get and check the arguments
- if Length(arg) = 1 then
- F := DefaultField( arg[1] );
- z := arg[1];
- elif Length(arg) = 2 then
- F := arg[1];
- if not IsField(F) then Error("<F> must be a field"); fi;
- z := arg[2];
- if not z in F then Error("<z> must lie in <F>"); fi;
- else
- Error("usage: Conjugates( [<F>,] <z> )");
- fi;
-
- # return the conjugates
- return F.operations.Conjugates( F, z );
- end;
-
- FieldOps.Conjugates := function ( F, z )
- local cnjs, # conjugates of <z> in <F>, result
- aut; # automorphism of <F>
-
- # compute the conjugates simply by applying all the automorphisms
- cnjs := [];
- for aut in Elements( GaloisGroup( F ) ) do
- Add( cnjs, z ^ aut );
- od;
-
- # return the conjugates
- return cnjs;
- end;
-
-
- #############################################################################
- ##
- #F Norm([<F>,]<z>) . . . . . . . . . . . . . . . . . norm of a field element
- ##
- Norm := function ( arg )
- local F, # field <F>, optional first argument
- z; # element <z>, second argument
-
- # get and check the arguments
- if Length(arg) = 1 then
- F := DefaultField( arg[1] );
- z := arg[1];
- elif Length(arg) = 2 then
- F := arg[1];
- if not IsField(F) then Error("<F> must be a field"); fi;
- z := arg[2];
- if not z in F then Error("<z> must lie in <F>"); fi;
- else
- Error("usage: Norm( [<F>,] <z> )");
- fi;
-
- # return the norm
- return F.operations.Norm( F, z );
- end;
-
- FieldOps.Norm := function ( F, z )
- return Product( Conjugates( F, z ) );
- end;
-
-
- #############################################################################
- ##
- #F Trace([<F>,]<z>) . . . . . . . . . . . . . . . trace of a field element
- ##
- Trace := function ( arg )
- local F, # field <F>, optional first argument
- z; # element <z>, second argument
-
- # get and check the arguments
- if Length(arg) = 1 then
- F := DefaultField( arg[1] );
- z := arg[1];
- elif Length(arg) = 2 then
- F := arg[1];
- if not IsField(F) then Error("<F> must be a field"); fi;
- z := arg[2];
- if not z in F then Error("<z> must lie in <F>"); fi;
- else
- Error("usage: Trace( [<F>,] <z> )");
- fi;
-
- # return the trace
- return F.operations.Trace( F, z );
- end;
-
- FieldOps.Trace := function ( F, z )
- return Sum( Conjugates( F, z ) );
- end;
-
-
- #############################################################################
- ##
- #F CharPol([<F>,]<z>) . . . . . . characteristic polynom of a field element
- ##
- CharPol := function ( arg )
- local F, # field <F>, optional first argument
- z; # element <z>, second argument
-
- # get and check the arguments
- if Length(arg) = 1 then
- F := DefaultField( arg[1] );
- z := arg[1];
- elif Length(arg) = 2 then
- F := arg[1];
- if not IsField(F) then Error("<F> must be a field"); fi;
- z := arg[2];
- if not z in F then Error("<z> must lie in <F>"); fi;
- else
- Error("usage: CharPol( [<F>,] <z> )");
- fi;
-
- # return the characteristic polynom
- return F.operations.CharPol( F, z );
- end;
-
- FieldOps.CharPol := function ( F, z )
- local pol, # characteristic polynom of <z> in <F>, result
- deg, # degree of <pol>
- con, # conjugate of <z> in <F>
- i; # loop variable
-
- # compute the trace simply by multiplying $x-cnj$
- pol := [ F.one ];
- deg := 0;
- for con in Conjugates( F, z ) do
- pol[deg+2] := pol[deg+1];
- for i in Reversed([2..deg+1]) do
- pol[i] := pol[i-1] - con * pol[i];
- od;
- pol[1] := F.zero - con * pol[1];
- deg := deg + 1;
- od;
-
- # return the characteristic polynom
- return pol;
- end;
-
-
- #############################################################################
- ##
- #F MinPol([<F>,]<z>) . . . . . . . . . . minimal polynom of a field element
- ##
- MinPol := function ( arg )
- local F, # field <F>, optional first argument
- z; # element <z>, second argument
-
- # get and check the arguments
- if Length(arg) = 1 then
- F := DefaultField( arg[1] );
- z := arg[1];
- elif Length(arg) = 2 then
- F := arg[1];
- if not IsField(F) then Error("<F> must be a field"); fi;
- z := arg[2];
- if not z in F then Error("<z> must lie in <F>"); fi;
- else
- Error("usage: MinPol( [<F>,] <z> )");
- fi;
-
- # return the minimal polynom
- return F.operations.MinPol( F, z );
- end;
-
- FieldOps.MinPol := function ( F, z )
- local pol, # minimal polynom of <z> in <F>, result
- deg, # degree of <pol>
- con, # conjugate of <z> in <F>
- i; # loop variable
-
- # compute the trace simply by multiplying $x-cnj$
- pol := [ F.one ];
- deg := 0;
- for con in Set( Conjugates( F, z ) ) do
- pol[deg+2] := pol[deg+1];
- for i in Reversed([2..deg+1]) do
- pol[i] := pol[i-1] - con * pol[i];
- od;
- pol[1] := F.zero - con * pol[1];
- deg := deg + 1;
- od;
-
- # return the minimal polynom
- return pol;
- end;
-
-
- #############################################################################
- ##
- #V FieldElements . . . . . . . . . . . . . . . domain of all field elements
- #V FieldElementsOps . operations record of the domain of all field elements
- ##
- ## 'FieldElements' is the domain of all field elements, i.e., rationals,
- ## cyclotomics, finite field elements, and record that implement field
- ## elements. Note that 'FieldElements' is not a field.
- ##
- ## 'FieldElementsOps' is the operations record for the 'FieldElements'
- ## domain. The operations record of other field domains like
- ## 'FiniteFieldElements' inherit default methods from this record.
- ##
- ## Those domains are known to 'FieldDomain', and they know how to create a
- ## field that contains a given list of elements.
- ##
- ## If you think this domain is superfluous I shall have to agree. It exists
- ## mainly to check the feasibility of this concept, which is convenient with
- ## groups, for categories besides groups.
- ##
- FieldElementsOps := Copy( DomainOps );
-
- FieldElementsOps.\in := function ( z, FieldElements )
- return IsRat( z )
- or IsCyc( z )
- or IsFFE( z )
- or IsRec( z ) and IsBound(z.isFieldElement) and z.isFieldElement;
- end;
-
- FieldElementsOps.Order := function ( F, z )
- local ord, elm;
- if z = F.zero then
- ord := 0;
- else
- elm := z;
- ord := 1;
- while elm <> F.one do
- elm := elm * z;
- ord := ord + 1;
- od;
- fi;
- return ord;
- end;
-
-
- FieldElements := rec();
- FieldElements.isDomain := true;
-
- FieldElements.name := "FieldElements";
-
- FieldElements.isFinite := false;
- FieldElements.size := "infinity";
-
- FieldElements.operations := FieldElementsOps;
-
-
- #############################################################################
- ##
- #F Field(<z>,...) . . . . . . . . . . . field containing a list of elements
- ##
- Field := function ( arg )
- local F, # field containing the elements of <arg>, result
- D; # domain containing the elements of <arg>
-
- # if called with one domain argument look in the operations record
- if Length(arg) = 1 and IsDomain(arg[1]) then
- F := arg[1].operations.Field( arg[1] );
-
- # special case for one square matrix
- elif Length(arg) = 1
- and IsMat(arg[1]) and Length(arg[1]) = Length(arg[1][1])
- then
- D := Domain( arg );
- F := D.operations.Field( arg );
-
- # special case for list of elements
- elif Length(arg) = 1 and IsList(arg[1]) then
- D := Domain( arg[1] );
- F := D.operations.Field( arg[1] );
-
- # other cases
- else
- D := Domain( arg );
- F := D.operations.Field( arg );
- fi;
-
- # return the field
- return F;
- end;
-
- FieldElementsOps.Field := function ( arg )
- Error("sorry, there is no default way to construct a field");
- end;
-
-
- #############################################################################
- ##
- #F DefaultField(<z>,...) . . . . default field containing a list of elements
- ##
- DefaultField := function ( arg )
- local F, # field containing the elements of <arg>, result
- D; # domain containing the elements of <arg>
-
- # special case for one square matrix
- if Length(arg) = 1
- and IsMat(arg[1]) and Length(arg[1]) = Length(arg[1][1])
- then
- D := Domain( arg );
- F := D.operations.DefaultField( arg );
-
- # special case for list of elements
- elif Length(arg) = 1 and IsList(arg[1]) then
- D := Domain( arg[1] );
- F := D.operations.DefaultField( arg[1] );
-
- # other cases
- else
- D := Domain( arg );
- F := D.operations.DefaultField( arg );
- fi;
-
- # return the default field
- return F;
- end;
-
- FieldElementsOps.DefaultField := function ( arg )
- Error("sorry, there is no default way to construct a default field");
- end;
-
-
- #############################################################################
- ##
- #F FieldOps.Polynomial( <R>, <coeffs>, <val> ) . polynomial over a ring <R>
- ##
- FieldOps.Polynomial := function( R, coeffs, val )
- local i, k, l, c;
-
- # remove leading zeros
- k := Length( coeffs );
- while 0 < k and coeffs[k] = R.zero do
- k := k - 1;
- od;
-
- # remove trailing zeros
- i := 0;
- while i < k and coeffs[i+1] = R.zero do
- i := i + 1;
- od;
-
- # now really remove zeros
- c := [];
- for l in [ i+1 .. k ] do
- c[l-i] := coeffs[l];
- od;
- if i < k then
- val := val + i;
- else
- val := 0;
- fi;
-
- # is vector might fail, but we ignore this
- IsVector(c);
-
- # return polynomial
- if val < 0 then
- return rec( coefficients := c,
- baseRing := R,
- isPolynomial := true,
- valuation := val,
- domain := LaurentPolynomials,
- operations := PolynomialOps );
- else
- return rec( coefficients := c,
- baseRing := R,
- isPolynomial := true,
- valuation := val,
- domain := Polynomials,
- operations := PolynomialOps );
- fi;
-
- end;
-
-
- #############################################################################
- ##
- #F FieldOps.PolynomialRing( <R> ) . . . . . . . . . . full polynomial ring
- ##
- FieldOps.PolynomialRing := function( F )
- local P;
-
- # construct a new ring domain
- P := rec();
- P.isDomain := true;
- P.isRing := true;
-
- # show that this a polynomial ring
- P.isPolynomialRing := true;
-
- # set known properties
- P.isFinite := false;
- P.size := "infinity";
-
- # add known properties of polynom ring over a field
- P.isCommutativeRing := true;
- P.isIntegralRing := true;
- P.isUniqueFactorizationRing := true;
- P.isEuclideanRing := true;
-
- # set one and zero
- P.one := Polynomial( F, [ F.one ] );
- P.zero := Polynomial( F, [] );
-
- # 'P.baseRing' contains <R>
- P.baseRing := F;
-
- # set operations record and return
- P.operations := PolynomialRingOps;
- return P;
-
- end;
-
-
- #############################################################################
- ##
- #F FieldOps.LaurentPolynomialRing( <F> ) . . . full Laurent polynomial ring
- ##
- FieldOps.LaurentPolynomialRing := function( F )
- local P;
-
- # construct a new ring domain
- P := rec();
- P.isDomain := true;
- P.isRing := true;
-
- # show that this a Laurent polynomial ring
- P.isLaurentPolynomialRing := true;
-
- # set known properties
- P.isFinite := false;
- P.size := "infinity";
-
- # add properties of laurent polynom ring over a field
- P.isCommutativeRing := true;
- P.isIntegralRing := true;
- P.isUniqueFactorizationRing := true;
- P.isEuclideanRing := true;
-
- # set one and zero
- P.one := Polynomial( F, [ F.one ] );
- P.zero := Polynomial( F, [] );
-
- # 'P.baseRing' contains <F>
- P.baseRing := F;
-
- # set operations record and return
- P.operations := FieldLaurentPolynomialRingOps;
- return P;
-
- end;
-
-
- #############################################################################
- ##
- #F FieldOps.Indeterminate( <F> ) . . . . . . . . indeterminate over a field
- ##
- FieldOps.Indeterminate := function( F )
- return Polynomial( F, [ F.zero, F.one ] );
- end;
-
-
- #############################################################################
- ##
- #F IsFieldHomomorphism(<fun>) . test if a function is a field homomorphism
- ##
- IsFieldHomomorphism := function ( fun )
- if not IsBound( fun.isFieldHomomorphism ) then
- fun.isFieldHomomorphism := fun.operations.IsFieldHomomorphism( fun );
- fi;
- return fun.isFieldHomomorphism;
- end;
-
-
- #############################################################################
- ##
- #F FieldOps.IsHomomorphism(<fun>) test if a function is a field homomorphism
- ##
- FieldOps.IsHomomorphism := IsFieldHomomorphism;
-
-
- #############################################################################
- ##
- #F MappingOps.IsFieldHomomorphism(<fun>) . . . test if a function is a field
- #F homomorphism
- ##
- MappingOps.IsFieldHomomorphism := function ( fun )
- local isHom; # 'true' if <fun> is a homomorphism, result
-
- # check that <fun> is a function
- if not IsMapping( fun ) then
- Error("<fun> must be a single valued mapping");
- fi;
-
- # test that source and range are fields
- if not IsField( fun.source ) then
- Error("'<fun>.source' must be a field");
- fi;
- if not IsField( fun.range ) then
- Error("'<fun>.range' must be a field");
- fi;
-
- # test the linearity explicitely if the source is finite
- if IsFinite( fun.source ) then
- isHom := ForAll( Elements(fun.source),
- x -> ForAll( Elements(fun.source),
- y -> Image( fun, x * y )
- = Image( fun, x ) * Image( fun, y )
- and Image( fun, x + y )
- = Image( fun, x ) + Image( fun, y ) ) );
-
- # otherwise give up
- else
- Error("sorry, can not test if <fun> is a hom., infinite source");
- fi;
-
- # return the result
- return isHom;
- end;
-
-
- #############################################################################
- ##
- #F KernelFieldHomomorphism(<fun>) . . . . . kernel of a field homomorphism
- ##
- KernelFieldHomomorphism := function ( fun )
- if not IsBound( fun.kernelFieldHomomorphism ) then
- fun.kernelFieldHomomorphism
- := fun.operations.KernelFieldHomomorphism(fun);
- fi;
- return fun.kernelFieldHomomorphism;
- end;
-
-
- #############################################################################
- ##
- #F FieldOps.Kernel(<fun>) . . . . . . . . . kernel of a field homomorphism
- ##
- FieldOps.Kernel := KernelFieldHomomorphism;
-
-
- #############################################################################
- ##
- #F MappingOps.KernelFieldHomomorphism(<hom>) kernel of a field homomorphism
- ##
- MappingOps.KernelFieldHomomorphism := function ( hom )
-
- # check that <hom> is a homomorphism
- if not IsHomomorphism(hom) then
- Error("<hom> must be a homomorphism");
- fi;
-
- # return the kernel
- return [ hom.source.zero ];
- end;
-
-
- #############################################################################
- ##
- #F FieldHomomorphismOps . . . . . operations record for field homomorphisms
- ##
- FieldHomomorphismOps := Copy( MappingOps );
-
-
- #############################################################################
- ##
- #F FieldHomomorphismOps.IsInjective(<hom>) . . . . . test if a homomorphism
- #F is injective
- ##
- FieldHomomorphismOps.IsInjective := function ( hom )
- return true;
- end;
-
-
- #############################################################################
- ##
- #F FieldHomomorphismOps.IsSurjective(<hom>) . . . . test if a homomorphism
- #F is surjective
- ##
- FieldHomomorphismOps.IsSurjective := function ( hom )
- return Size( hom.range ) = Size( Image( hom ) );
- end;
-
-
- #############################################################################
- ##
- #F FieldHomomorphismOps.IsFieldHomomorphism(<hom>) . . . . . . . always true
- ##
- FieldHomomorphismOps.IsFieldHomomorphism := function ( hom )
- return true;
- end;
-
-
- #############################################################################
- ##
- #F FieldHomomorphismOps.\=(<hom1>,<hom2>) . . . comparison of homomorphisms
- ##
- FieldHomomorphismOps.\= := function ( hom1, hom2 )
- local isEql;
-
- # if <hom1> is a homomorphisms
- if IsHomomorphism( hom1 ) then
-
- # and if <hom2> is a homomorphisms
- if IsHomomorphism( hom2 ) then
-
- # maybe the properties we already know determine the result
- if (IsBound(hom1.isInjective) and IsBound(hom2.isInjective)
- and hom1.isInjective <> hom2.isInjective)
- or (IsBound(hom1.isSurjective) and IsBound(hom2.isSurjective)
- and hom1.isSurjective <> hom2.isSurjective)
- then
- isEql := false;
-
- # otherwise we must really test the equality
- else
- isEql := hom1.source = hom2.source
- and hom1.range = hom2.range
- and ForAll( hom1.source.generators,
- elm -> Image(hom1,elm) = Image(hom2,elm) );
- fi;
-
- # a homomorphism and an object of another type are never equal
- else
- isEql := false;
- fi;
-
- # if <hom1> is not a homomorphism
- else
-
- # a homomorphism and an object of another type are never equal
- if IsHomomorphism( hom2 ) then
- isEql := false;
-
- # at least one argument must be a mapping
- else
- Error("panic, either <hom1> or <hom2> must be a mapping");
- fi;
-
- fi;
-
- # return the result
- return isEql;
- end;
-
-
- #############################################################################
- ##
- #F FieldHomomorphismOps.ImagesSet(<hom>,<elms>) images of a set under a hom
- ##
- FieldHomomorphismOps.ImagesSet := function ( hom, elms )
- if IsField( elms ) and IsSubset( hom.source, elms ) then
- return Field( List( elms.generators, gen -> Image( hom, gen ) ) );
- else
- return MappingOps.ImagesSet( hom, elms );
- fi;
- end;
-
-
- #############################################################################
- ##
- #F FieldHomomorphismOps.PreImagesElm(<hom>,<elm>) . . . preimage of an elm
- ##
- FieldHomomorphismOps.PreImagesElm := function ( hom, elm )
- return [ PreImagesRepresentative( hom, elm ) ];
- end;
-
-
- #############################################################################
- ##
- #F FieldHomomorphismOps.PreImagesSet(<hom>,<elm>) . . . . preimage of a set
- ##
- FieldHomomorphismOps.PreImagesSet := function ( hom, elms )
- if IsField( elms ) and IsSubset( hom.range, elms ) then
- return Field( List( elms.generators,
- gen -> PreImagesRepresentative( hom, gen ) ) );
- else
- return MappingOps.PreImagesSet( hom, elms );
- fi;
- end;
-
-
- #############################################################################
- ##
- #F FieldHomomorphismOps.CompositionMapping(<map1>,<map2>)composition of homs
- ##
- FieldHomomorphismOps.CompositionMapping := function ( map1, map2 )
- local com; # composition of <map1> and <map2>, result
-
- # handle the composition of two homomorphisms
- if IsFieldHomomorphism( map1 ) and IsFieldHomomorphism( map2 ) then
-
- # make the mapping record
- com := rec();
- com.isGeneralMapping := true;
-
- # enter the source and the range
- com.source := map2.source;
- com.range := map1.range;
-
- # maybe we know that the mapping is a function
- com.isMapping := true;
- com.isHomomorphism := true;
-
- # enter the identifying information
- com.map1 := map1;
- com.map2 := map2;
-
- # enter the operations record
- com.operations := CompositionFieldHomomorphismOps;
-
- # handle other mappings
- else
-
- com := MappingOps.CompositionMapping( map1, map2 );
-
- fi;
-
- # return the composition
- return com;
- end;
-
- CompositionFieldHomomorphismOps := Copy( CompositionMappingOps );
-
- CompositionFieldHomomorphismOps.IsInjective :=
- FieldHomomorphismOps.IsInjective;
-
- CompositionFieldHomomorphismOps.IsSurjective :=
- FieldHomomorphismOps.IsSurjective;
-
- CompositionFieldHomomorphismOps.IsFieldHomomorphism :=
- FieldHomomorphismOps.IsFieldHomomorphism;
-
- CompositionFieldHomomorphismOps.\= :=
- FieldHomomorphismOps.\=;
-
- CompositionFieldHomomorphismOps.ImageElm := function ( com, elm )
- return com.map1.operations.ImageElm( com.map1,
- com.map2.operations.ImageElm( com.map2,
- elm ) );
- end;
-
- CompositionFieldHomomorphismOps.PreImagesElm :=
- FieldHomomorphismOps.PreImagesElm;
-
- CompositionFieldHomomorphismOps.KernelFieldHomomorphism := function ( com )
- return [ com.map2.source.zero ];
- end;
-
- CompositionFieldHomomorphismOps.Print := function ( com )
- Print( "(", com.map2, " * ", com.map1, ")" );
- end;
-
-
- #############################################################################
- ##
- #F FieldOps.IdentityMapping(<G>) . . . . . . . . identity mapping on a field
- ##
- FieldOps.IdentityMapping := function ( G )
- local id; # identity mapping on <G>, result
-
- # make the mapping
- id := rec();
- id.isGeneralMapping := true;
-
- # enter the identification
- id.isIdentity := true;
- id.source := G;
- id.range := G;
-
- # enter usefull information
- id.isMapping := true;
- id.isInjective := true;
- id.isSurjective := true;
- id.isFieldHomomorphism := true;
- id.image := G;
- id.preImage := G;
-
- # enter the operations record
- id.operations := IdentityFieldHomomorphismOps;
-
- # return the mapping
- return id;
- end;
-
- IdentityFieldHomomorphismOps := Copy( MappingOps );
-
- IdentityFieldHomomorphismOps.ImageElm := function ( id, elm )
- return elm;
- end;
-
- IdentityFieldHomomorphismOps.ImagesElm := function ( id, elm )
- return [ elm ];
- end;
-
- IdentityFieldHomomorphismOps.ImagesSet := function ( id, elms )
- return elms;
- end;
-
- IdentityFieldHomomorphismOps.PreImageElm := function ( id, elm )
- return elm;
- end;
-
- IdentityFieldHomomorphismOps.PreImagesElm := function ( id, elm )
- return [ elm ];
- end;
-
- IdentityFieldHomomorphismOps.PreImagesSet := function ( id, elms )
- return elms;
- end;
-
- IdentityFieldHomomorphismOps.\= := FieldHomomorphismOps.\=;
-
- IdentityFieldHomomorphismOps.\< := FieldHomomorphismOps.\<;
-
- IdentityFieldHomomorphismOps.CompositionMapping := function ( map1, map2 )
- if IsBound( map1.isIdentity ) then
- return map2;
- elif IsBound( map2.isIdentity ) then
- return map1;
- else
- Error("panic, neither <map1> nor <map2> is the identity");
- fi;
- end;
-
- IdentityFieldHomomorphismOps.InverseMapping := function ( id )
- return id;
- end;
-
- IdentityFieldHomomorphismOps.Print := function ( id )
- Print("IdentityMapping( ",id.source," )");
- end;
-
-
- #############################################################################
- ##
- #E Emacs . . . . . . . . . . . . . . . . . . . . . . . local emacs variables
- ##
- ## Local Variables:
- ## mode: outline
- ## outline-regexp: "#F\\|#V\\|#E"
- ## fill-column: 73
- ## fill-prefix: "## "
- ## eval: (hide-body)
- ## End:
- ##
-
-
-
-