############################################################################# ## ## This file is part of GAP, a system for computational discrete algebra. ## This file's authors include Steve Linton. ## ## 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 `FFE's represented as library objects by ## coefficients of polynomials modulo the Conway polynomial. ##
############################################################################# ## #R IsCoeffsModConwayPolRep( <obj> ) ## ## An element in this representation is stored a three component ## PositionalObject ## ## The first component is a mutable vector giving the coefficients of a polynomial ## over a prime field. Where appropriate, this should be compressed. ## ## The second component is an integer specifying the degree of the field extension ## over the prime field in which this element is written. ## ## The third component may hold the representation of the element written over ## the field extension that it generates. If this is 'fail' then this is not known ## if it is 'false' then the element is known to be irreducible. This value may be ## an internal FFE or a ZmodpZ object. ## ## ##
############################################################################# ## #V FFECONWAY is a holder for private function ##
BindGlobal("FFECONWAY", rec());
############################################################################# ## #F FFECONWAY.ZNC(<p>,<d>) .. construct a primitive root ## ## this function also deals with construction and caching of the ## Conway Polynomial and associated data. It must always be called before ## any computation with elements of GF(p^d) ## ## To support computing with these objects, a variety of data is stored in the ## FFEFamily: ## ## 'fam!.ConwayFldEltDefaultType' contains the type of the field elements in this ## characteristic and representation ## 'fam!.ConwayPolCoeffs[d]' contains the coefficients of the Conway Polynomial ## for GF(p^d) ## 'fam!.ConwayFldEltReducers[d]' contains a function which will take a mutable ## vector of FFEs in compressed format (if appropriate) ## reduce it modulo the Conway polynomial and fix its ## length to be exactly 'd' ## 'fam!.ZCache[d]' contains 'Z(p,d)' once it has been computed. ##
FFECONWAY.SetUpConwayStuff := function(p,d)
local fam, cp, cps, i, reducer;
fam := FFEFamily(p); if not IsBound(fam!.ConwayPolCoeffs) then
fam!.ConwayPolCoeffs := [];
fam!.ConwayFldEltReducers := []; fi;
if IsBound(fam!.ConwayPolCoeffs[d]) then
return; fi;
if not IsCheapConwayPolynomial(p,d) then
Error("Conway Polynomial ",p,"^",d, " will need to computed and might be slow\n", "return to continue"); fi; cp := CoefficientsOfUnivariatePolynomial(ConwayPolynomial(p,d));
# # various cases for reducers # if p = 2then
reducer := function(v)
REDUCE_COEFFS_GF2VEC(v,Length(v),cp,d+1);
RESIZE_GF2VEC(v,d); end; elif p <= 256then # # We can save time on repeated reductions using # pre-computed shifts #
cps := MAKE_SHIFTED_COEFFS_VEC8BIT(cp,d+1);
reducer := function(v)
REDUCE_COEFFS_VEC8BIT(v,Length(v),cps);
RESIZE_VEC8BIT(v,d); end; else # # Need to adjust the length "by hand" #
reducer := function(v)
ReduceCoeffs(v,Length(v),cp,d+1); if Length(v) < d then
PadCoeffs(v,d); elif Length(v) > d then for i in [d+1..Length(v)] do
Unbind(v[i]);
od; fi; end; fi;
FFECONWAY.ZNC := function(p,d)
local fam, zc, v;
fam := FFEFamily(p);
if not IsBound(fam!.ZCache) then
fam!.ZCache := []; fi;
if IsBound(fam!.ZCache[d]) then
return fam!.ZCache[d]; fi;
zc := fam!.ZCache; if not IsBound(fam!.ConwayFldEltDefaultType) then
fam!.ConwayFldEltDefaultType := NewType(fam, IsCoeffsModConwayPolRep and IsLexOrderedFFE); fi;
FFECONWAY.SetUpConwayStuff(p,d);
v := ListWithIdenticalEntries(d,0*Z(p));
v[2] := Z(p)^0;
ConvertToVectorRep(v,p);
# put 'false' in the third component because we know it is irreducible
zc[d] := Objectify(fam!.ConwayFldEltDefaultType, [v,d,false]);
return zc[d]; end;
############################################################################# ## #M Z(p,d), Z(q) .. ## ## check various things and call FFECONWAY.ZNC
InstallOtherMethod(ZOp,
[IsPosInt, IsPosInt], function(p,d)
local q; if not IsPrimeInt(p) then
Error("Z: <p> must be a prime (not the integer ", p, ")"); fi;
q := p^d; if q <= MAXSIZE_GF_INTERNAL or d =1then
return Z(q); fi;
return FFECONWAY.ZNC(p,d); end);
InstallMethod(ZOp,
[IsPosInt], function(q)
local p, d; if q <= MAXSIZE_GF_INTERNAL then
TryNextMethod(); # should never happen fi;
p := SmallestRootInt(q);
d := LogInt(q,p);
Assert(1, q=p^d); if not IsPrimeInt(p) then
Error("Z: <q> must be a positive prime power (not the integer ", q, ")"); fi; if d > 1then
return FFECONWAY.ZNC(p,d); fi;
TryNextMethod(); end);
InstallMethod(String,"for large finite field elements",
[IsFFE and IsCoeffsModConwayPolRep], function(x)
local started, coeffs, fam, s, str, i; if not IsBool(x![3]) then
return String(x![3]); fi;
started := false;
coeffs := x![1];
fam := FamilyObj(x);
s := Concatenation("Z(",String(fam!.Characteristic),",",String(x![2]),")"); if Length(coeffs) = 0then
str := "0*";
Append(str,s);
return str; fi;
str := ""; if not IsZero(coeffs[1]) then
Append(str,String(coeffs[1]));
started := true; fi; for i in [2..Length(coeffs)] do if not IsZero(coeffs[i]) then if started then
Add(str,'+'); fi; if not IsOne(coeffs[i]) then
Append(str,String(IntFFE(coeffs[i])));
Add(str,'*'); fi;
Append(str,s); if i > 2then
Add(str,'^');
Append(str,String(i-1)); fi;
started := true; fi;
od; if not started then
str := "0*";
Append(str,s); fi;
return str; end);
InstallMethod(PrintObj, "for large finite field elements (use String)",
[IsFFE and IsCoeffsModConwayPolRep], function(x)
Print(String(x)); end);
BindGlobal( "DisplayStringForLargeFiniteFieldElements", function(x)
local s, j, a; if IsZero(x) then
return "0z\n"; elif IsOne(x) then
return "z0\n"; fi;
s := ""; for j in [0..x![2]-1] do
a := IntFFE(x![1][j+1]); if a <> 0then if Length(s) <> 0then
Append(s,"+"); fi; if a <> 1 or j = 0then
Append(s,String(a)); fi; if j <> 0then
Append(s,"z"); if j <> 1then
Append(s,String(j)); fi; fi; fi;
od;
Add(s,'\n');
return s; end );
InstallMethod(DisplayString,"for large finite field elements",
[IsFFE and IsCoeffsModConwayPolRep],
DisplayStringForLargeFiniteFieldElements );
InstallMethod(Display,"for large finite field elements",
[IsFFE and IsCoeffsModConwayPolRep], function(x)
Print(DisplayString(x)); end);
InstallMethod(ViewString,"for large finite field elements",
[IsFFE and IsCoeffsModConwayPolRep], function(x)
local s;
s := DisplayStringForLargeFiniteFieldElements(x); if Length(s) > GAPInfo.ViewLength*SizeScreen()[1] then
return Concatenation("<<an element of GF(",
String(Characteristic(x)), ", ",
String(DegreeFFE(x)),")>>"); else
Remove(s); # get rid of trailing newline
return s; fi; end);
InstallMethod(ViewObj, "for large finite field elements",
[IsFFE and IsCoeffsModConwayPolRep], function(x)
Print(ViewString(x)); end);
############################################################################# ## #F FFECONWAY.GetConwayPolCoeffs( <family>, <degree>) ## ## returns stored Conway Polynomial coefficients from family ## triggers computation if needed. ##
FFECONWAY.GetConwayPolCoeffs := function(f,d)
local p; if not IsBound(f!.ConwayPolCoeffs) then
f!.ConwayPolCoeffs := []; fi; if not IsBound(f!.ConwayPolCoeffs[d]) then
p := f!.Characteristic;
FFECONWAY.SetUpConwayStuff(p,d); fi;
return f!.ConwayPolCoeffs[d]; end;
############################################################################# ## #F FFECONWAY.FiniteFieldEmbeddingRecord(<prime>, <smalldeg>, <bigdeg> ) ## ## returns a record (stored in the family after it is first computed) ## describing the embedding of F1 = GF(p^d1) into F2= GF(p^d2). The components ## of this record are: ## ## mat: a <d1> x <d2> matrix whose rows are the canonical basis of F1 ## semi: a semi-echelonized version of mat ## convert: a <d1> x <d1> matrix such that <convert>*<mat> = <semi> ## pivots: a vector giving the position of the first non-zero entry in each ## row of <semi> ##
FFECONWAY.FiniteFieldEmbeddingRecord := function(p, d1,d2)
local fam, c, n, zz, x, z1, m, z, i, r, res;
fam := FFEFamily(p); if not IsBound(fam!.embeddingRecords) then
fam!.embeddingRecords := []; fi; if not IsBound(fam!.embeddingRecords[d2]) then
fam!.embeddingRecords[d2] := []; fi; if not IsBound(fam!.embeddingRecords[d2][d1]) then
c := FFECONWAY.GetConwayPolCoeffs(fam,d2);
n := (p^d2-1)/(p^d1-1);
zz := 0*Z(p);
x := [zz,Z(p)^0];
ConvertToVectorRep(x,p);
z1 := PowerModCoeffs(x,n,c);
fam!.ConwayFldEltReducers[d2](z1);
m := [ZeroMutable(z1),z1];
m[1,1] := Z(p)^0;
z := z1; for i in [2..d1-1] do
z := ProductCoeffs(z,z1);
fam!.ConwayFldEltReducers[d2](z);
Add(m,z);
od;
ConvertToMatrixRep(m,p);
r := rec( mat := m);
res := SemiEchelonMatTransformation(r.mat);
r.semi := res.vectors;
r.convert := res.coeffs;
r.pivots := []; for i in [1..Length(res.heads)] do if res.heads[i] > 0then
r.pivots[res.heads[i]] := i; fi;
od;
Assert(2,d1 = 1 or res.relations = []);
fam!.embeddingRecords[d2][d1] := r; fi;
return fam!.embeddingRecords[d2][d1]; end;
############################################################################# ## #F FFECONWAY.WriteOverLargerField( <ffe>, <bigdeg> ) ## ## returns an element written over a field of degree <bigdeg>, but equal to <ffe> ## <ffe> can be an internal FFE or a ZmodpZ object ##
FFECONWAY.WriteOverLargerField := function(x,d2)
local fam, p, d1, v, f, y;
fam := FamilyObj(x);
p := fam!.Characteristic; if p^d2 <= MAXSIZE_GF_INTERNAL then
return x; fi; if not IsCoeffsModConwayPolRep(x) then
d1 := DegreeFFE(x); if d1 = d2 then
return x; fi;
v := Coefficients(CanonicalBasis(AsField(GF(p,1),GF(p,d1))),x); else
d1 := x![2]; if d1 = d2 then
return x; fi;
v := x![1]; fi;
Assert(1,d2 mod d1 = 0);
f := FFECONWAY.FiniteFieldEmbeddingRecord(p,d1,d2); if not IsCoeffsModConwayPolRep(x) or x![3] = false then
y := x; elif x![3] <> fail then
y := x![3]; else
y := fail; fi;
return Objectify(fam!.ConwayFldEltDefaultType, [v*f!.mat,d2,y]); end;
############################################################################# ## #F FFECONWAY.TryToWriteInSmallerField( <ffe>, <smalldeg> ) ## ## returns an element written over a field of degree <smalldeg>, but equal to <ffe> ## if possible, otherwise fail. The returned element may be an internal FFE ## or a ZmodpZ object. ##
FFECONWAY.TryToWriteInSmallerField := function(x,d1)
local dmin, fam, p, d2, smalld, r, v, v2, i, piv, w,
oversmalld, z; if IsInternalRep(x) then
return fail; fi; if IsZmodpZObj(x) then
return fail; fi; if d1 = x![2] then
return fail; fi; if x![3] = false then
return fail; fi; if x![3] <> fail then if IsCoeffsModConwayPolRep(x![3]) then
dmin := x![3]![2]; else
dmin := DegreeFFE(x![3]); fi; if dmin = d1 then
return x![3]; elif d1 mod dmin = 0then
return FFECONWAY.WriteOverLargerField(x![3],d1); else
return fail; fi; fi;
fam := FamilyObj(x);
p := fam!.Characteristic;
d2 := x![2]; if not IsMutable(x![1]) then
x![1] := ShallowCopy(x![1]); fi;
PadCoeffs(x![1],d2);
smalld := Gcd(d1,d2);
r := FFECONWAY.FiniteFieldEmbeddingRecord(p, smalld,d2);
v := ShallowCopy(x![1]);
v2 := ZeroMutable(r.convert[1]); for i in [1..smalld] do
piv := r.pivots[i];
w := r.semi[i];
x := v[piv]/w[piv];
AddCoeffs(v,w,-x);
AddCoeffs(v2,r.convert[i],x);
od; if not IsZero(v) then
return fail; fi; if d1 = 1then
oversmalld := v2[1]; elif p^d1 <= MAXSIZE_GF_INTERNAL then
z := Z(p^smalld);
oversmalld := Sum([1..smalld], i-> z^(i-1)*v2[i]);
else
oversmalld := Objectify(fam!.ConwayFldEltDefaultType,[v2,d1,fail]); fi; if smalld < d1 then
return FFECONWAY.WriteOverLargerField(oversmalld, d1); else
return oversmalld; fi; end;
############################################################################# ## #F FFECONWAY.WriteOverSmallestField( <ffe> ) ## ## Returns <ffe> written over the field it generates. ##
FFECONWAY.WriteOverSmallestField := function(x)
local d, f, fac, l, d1, x1, x2; if IsInternalRep(x) or IsZmodpZObj(x) then
return x; fi; if x![3] = false then
return x; elif x![3] <> fail then
return x![3]; fi;
d := x![2];
f := Collected(Factors(Integers,d)); for fac in f do
l := fac[1];
d1 := d/l;
x1 := FFECONWAY.TryToWriteInSmallerField(x,d1); if x1 <> fail then
x2 := FFECONWAY.WriteOverSmallestField(x1);
x![3] := x2;
return x2; fi;
od;
x![3] := false;
return x; end;
InstallMethod(DegreeFFE, [IsCoeffsModConwayPolRep and IsFFE], function(x)
local y;
y := FFECONWAY.WriteOverSmallestField(x); if IsCoeffsModConwayPolRep(y) then
return y![2]; else
return DegreeFFE(y); fi; end);
############################################################################# ## #M \=(<ffe>,<ffe>) ## ## Includes equality with internal FFE and ZmodpZ objects ##
InstallMethod(\=,
IsIdenticalObj,
[IsCoeffsModConwayPolRep and IsFFE, IsCoeffsModConwayPolRep and IsFFE], function(x1,x2)
local d1, d2, y2, y1, d;
d1 := x1![2];
d2 := x2![2]; if d1 = d2 then
return x1![1] = x2![1]; fi; if d2 mod d1 = 0then
y2 := FFECONWAY.TryToWriteInSmallerField(x2,d1); if y2 = fail then
return false; else
return y2![1] = x1![1]; fi; elif d1 mod d2 = 0then
y1 := FFECONWAY.TryToWriteInSmallerField(x1,d2); if y1 = fail then
return false; else
return y1![1] = x2![1]; fi; else
d := Gcd(d1,d2);
y1 := FFECONWAY.TryToWriteInSmallerField(x1,d); if y1 = fail then
return false; fi;
y2 := FFECONWAY.TryToWriteInSmallerField(x2,d); if y2 = fail then
return false; fi;
return y1 = y2; fi; end);
InstallMethod(\=,
IsIdenticalObj,
[IsCoeffsModConwayPolRep and IsFFE, IsFFE], function(x1,x2)
local d2, y1;
d2 := DegreeFFE(x2);
y1 := FFECONWAY.TryToWriteInSmallerField(x1,d2); if y1 = fail then
return false; else
return y1 = x2; fi; end);
InstallMethod(\=,
IsIdenticalObj,
[ IsFFE, IsCoeffsModConwayPolRep and IsFFE], function(x1,x2)
local d1, y2;
d1 := DegreeFFE(x1);
y2 := FFECONWAY.TryToWriteInSmallerField(x2,d1); if y2 = fail then
return false; else
return y2 = x1; fi; end);
############################################################################# ## #F FFECONWAY.CoeffsOverCommonField(<ffe>,<ffe>) .. utility function ## ## Returns a length 3 list. The first and second entries of the ## list are the coefficient vectors of the two arguments written over ## a field which contains both of them, whose degree is the third entry ##
FFECONWAY.CoeffsOverCommonField := function(x1,x2)
local fam, d1, d2, v1, v2, d, y2, y1;
fam := FamilyObj(x1); if IsCoeffsModConwayPolRep(x1) then
d1 := x1![2];
v1 := x1![1]; else
d1 := DegreeFFE(x1); fi; if IsCoeffsModConwayPolRep(x2) then
d2 := x2![2];
v2 := x2![1]; else
d2 := DegreeFFE(x2); fi; if d1 = d2 then
d := d1; elif d1 mod d2 = 0then
y2 := FFECONWAY.WriteOverLargerField(x2,d1);
v2 := y2![1];
d := d1; elif d2 mod d1 = 0then
y1 := FFECONWAY.WriteOverLargerField(x1,d2);
v1 := y1![1];
d := d2; else
d := Lcm(d1,d2);
Z(Characteristic(fam),d);
y1 := FFECONWAY.WriteOverLargerField(x1,d);
v1 := y1![1];
y2 := FFECONWAY.WriteOverLargerField(x2,d);
v2 := y2![1]; fi;
return [v1,v2,d]; end;
############################################################################# ## #F FFECONWAY.SumConwayOtherFFEs( <ffe1>, <ffe2> ) .. Sum method ## this is the sum method for cases where one of the summands might ## not be in the Conway field representation. ##
FFECONWAY.SumConwayOtherFFEs := function(x1,x2)
local fam, cc, v;
fam := FamilyObj(x1);
cc := FFECONWAY.CoeffsOverCommonField(x1,x2);
v := cc[1]+cc[2];
return Objectify(fam!.ConwayFldEltDefaultType, [v,cc[3],fail]); end;
############################################################################# ## #M \+(<ffe1>,<ffe2>) ## ## try and be quick in the common case of two Conway elements over the same field. ## also handle all other cases.
InstallMethod(\+,
IsIdenticalObj,
[ IsCoeffsModConwayPolRep and IsFFE,
IsCoeffsModConwayPolRep and IsFFE], function(x1,x2)
local v, d, cc, fam; if x1![2] = x2![2] then
v := x1![1]+x2![1];
d := x1![2]; else
cc := FFECONWAY.CoeffsOverCommonField(x1,x2);
v := cc[1]+cc[2];
d := cc[3]; fi;
fam := FamilyObj(x1);
return Objectify(fam!.ConwayFldEltDefaultType,
[v,d,fail]); end);
InstallMethod(\+,
IsIdenticalObj,
[ IsCoeffsModConwayPolRep and IsFFE,
IsFFE],
FFECONWAY.SumConwayOtherFFEs
);
InstallMethod(\+,
IsIdenticalObj,
[ IsFFE,
IsCoeffsModConwayPolRep and IsFFE],
FFECONWAY.SumConwayOtherFFEs
);
InstallMethod(SUM_FFE_LARGE,
IsIdenticalObj,
[ IsFFE and IsInternalRep,
IsFFE and IsInternalRep],
FFECONWAY.SumConwayOtherFFEs);
FFECONWAY.CATCH_UNEQUAL_CHARACTERISTIC := function(x,y) if Characteristic(x) <> Characteristic(y) then
Error("Binary operation on finite field elements: characteristics must match\n"); fi;
TryNextMethod(); end;
############################################################################# ## #F FFECONWAY.DiffConwayOtherFFEs( <ffe1>, <ffe2> ) .. Sum method ## this is the sum method for cases where one of the summands might ## not be in the Conway field representation. ##
FFECONWAY.DiffConwayOtherFFEs := function(x1,x2)
local fam, cc, v;
fam := FamilyObj(x1);
cc := FFECONWAY.CoeffsOverCommonField(x1,x2);
v := cc[1]-cc[2];
return Objectify(fam!.ConwayFldEltDefaultType, [v,cc[3],fail]); end;
############################################################################# ## #M \-(<ffe1>,<ffe2>) ## ## try and be quick in the common case of two Conway elements over the same field. ## also handle all other cases.
InstallMethod(\-,
IsIdenticalObj,
[ IsCoeffsModConwayPolRep and IsFFE,
IsCoeffsModConwayPolRep and IsFFE], function(x1,x2)
local v, d, cc, fam; if x1![2] = x2![2] then
v := x1![1]-x2![1];
d := x1![2]; else
cc := FFECONWAY.CoeffsOverCommonField(x1,x2);
v := cc[1]-cc[2];
d := cc[3]; fi;
fam := FamilyObj(x1);
return Objectify(fam!.ConwayFldEltDefaultType,
[v,d,fail]); end);
InstallMethod(\-,
IsIdenticalObj,
[ IsCoeffsModConwayPolRep and IsFFE,
IsFFE],
FFECONWAY.DiffConwayOtherFFEs
);
InstallMethod(\-,
IsIdenticalObj,
[ IsFFE,
IsCoeffsModConwayPolRep and IsFFE],
FFECONWAY.DiffConwayOtherFFEs
);
InstallMethod(DIFF_FFE_LARGE,
IsIdenticalObj,
[ IsFFE and IsInternalRep,
IsFFE and IsInternalRep],
FFECONWAY.DiffConwayOtherFFEs);
InstallMethod(\*,
IsIdenticalObj,
[ IsCoeffsModConwayPolRep and IsFFE,
IsCoeffsModConwayPolRep and IsFFE], function(x1,x2)
local v, d, cc, fam; if x1![2] = x2![2] then
v := ProductCoeffs(x1![1],x2![1]);
d := x1![2]; else
cc := FFECONWAY.CoeffsOverCommonField(x1,x2);
v := ProductCoeffs(cc[1],cc[2]);
d := cc[3]; fi;
fam := FamilyObj(x1);
fam!.ConwayFldEltReducers[d](v);
return Objectify(fam!.ConwayFldEltDefaultType,
[v,d,fail]); end
);
InstallMethod(\*,
IsIdenticalObj,
[ IsFFE,
IsCoeffsModConwayPolRep and IsFFE],
FFECONWAY.ProdConwayOtherFFEs
);
InstallMethod(\*,
IsIdenticalObj,
[ IsCoeffsModConwayPolRep and IsFFE,
IsFFE ],
FFECONWAY.ProdConwayOtherFFEs
);
InstallMethod(PROD_FFE_LARGE,
IsIdenticalObj,
[ IsFFE and IsInternalRep,
IsFFE and IsInternalRep],
FFECONWAY.ProdConwayOtherFFEs);
InstallMethod(AdditiveInverseOp,
[ IsCoeffsModConwayPolRep and IsFFE], function(x)
local fam, y;
fam := FamilyObj(x); if IsBool(x![3]) then
y := x![3]; else
y := -x![3]; fi;
return Objectify(fam!.ConwayFldEltDefaultType, [AdditiveInverseMutable(x![1]),x![2],y]); end);
############################################################################# ## #M Inverse -- uses Euclids algorithm to express the GCD of x and the ConwayPolynomial ## (which had better be 1!) as r.x + s.c (actually don't compute s). Then r is ## the inverse of x. ##
InstallMethod(InverseOp,
[ IsCoeffsModConwayPolRep and IsFFE], function(x)
local t, fam, p, d, c, a, b, r, s, qr, y;
fam := FamilyObj(x);
p := fam!.Characteristic;
d := x![2];
c := FFECONWAY.GetConwayPolCoeffs(fam,d);
a := ShallowCopy(x![1]);
b := ShallowCopy(c);
r := [Z(p)^0];
ConvertToVectorRep(r,p);
s := ZeroMutable(r);
ShrinkRowVector(a); if Length(a) = 0then
return fail; fi; while Length(a) > 1do
qr := QuotRemCoeffs(b,a);
b := a;
a := qr[2];
ShrinkRowVector(a);
t := r;
r := s-ProductCoeffs(r,qr[1]);
s := t;
od;
Assert(1,Length(a) = 1);
MultVector(r,Inverse(a[1])); if AssertionLevel() >= 2then
t := ProductCoeffs(x![1],r);
fam!.ConwayFldEltReducers[d](t); if not IsOne(t[1]) or ForAny([2..Length(t)], i->not IsZero(t[i])) then
Error("Inverse has failed"); fi; fi;
fam!.ConwayFldEltReducers[d](r); if IsBool(x![3]) then
y := x![3]; else
y := Inverse(x![3]); fi;
return Objectify(fam!.ConwayFldEltDefaultType,[r,d,y]); end);
InstallMethod(QUO_FFE_LARGE,
IsIdenticalObj,
[ IsFFE and IsInternalRep,
IsFFE and IsInternalRep], function(x,y)
return FFECONWAY.ProdConwayOtherFFEs(x,y^-1); end);
InstallMethod(IsZero,
[ IsCoeffsModConwayPolRep and IsFFE],
x-> IsZero(x![1]));
############################################################################# ## #M IsOne -- coefficients vector must be [1,0,..0] ##
InstallMethod(IsOne,
[ IsCoeffsModConwayPolRep and IsFFE], function(x)
local v, i;
v := x![1]; if not IsOne(v[1]) then
return false; fi; for i in [2..Length(v)] do if not IsZero(v![i]) then
return false; fi;
od;
return true; end);
############################################################################# ## #M ZeroOp -- Make a zero. ##
FFECONWAY.Zero := function(x)
local fam, d;
fam := FamilyObj(x); if not IsBound(fam!.ZeroConwayFFEs) then
fam!.ZeroConwayFFEs := []; fi;
d := x![2]; if not IsBound(fam!.ZeroConwayFFEs[d]) then
fam!.ZeroConwayFFEs[d] := Objectify(fam!.ConwayFldEltDefaultType,[ZeroMutable(x![1]),d, 0*Z(fam!.Characteristic)]); fi;
return fam!.ZeroConwayFFEs[d]; end;
InstallMethod(ZeroOp,
[ IsCoeffsModConwayPolRep and IsFFE],
FFECONWAY.Zero);
InstallMethod(ZeroImmutable,
[ IsCoeffsModConwayPolRep and IsFFE],
FFECONWAY.Zero);
FFECONWAY.One := function(x)
local fam, d, v;
fam := FamilyObj(x); if not IsBound(fam!.OneConwayFFEs) then
fam!.OneConwayFFEs := []; fi;
d := x![2]; if not IsBound(fam!.OneConwayFFEs[d]) then
v := ZeroMutable(x![1]);
v[1] := Z(fam!.Characteristic)^0;
fam!.OneConwayFFEs[d] := Objectify(fam!.ConwayFldEltDefaultType,[v,d,
Z(fam!.Characteristic)^0]); fi;
return fam!.OneConwayFFEs[d]; end;
InstallMethod(OneOp,
[ IsCoeffsModConwayPolRep and IsFFE],
FFECONWAY.One);
InstallMethod(OneImmutable,
[ IsCoeffsModConwayPolRep and IsFFE],
FFECONWAY.One);
############################################################################# ## #M \< this is a bit complicated due to the rules for comparing FFEs in GAP ## We have to identify the smallest field representation of our elements ## then deal with the possibility that that is in another representation ##
InstallMethod(\<,
IsIdenticalObj,
[ IsCoeffsModConwayPolRep and IsLexOrderedFFE,
IsCoeffsModConwayPolRep and IsLexOrderedFFE ], function(x1,x2)
local y1, y2, d1, d2;
y1 := FFECONWAY.WriteOverSmallestField(x1);
y2 := FFECONWAY.WriteOverSmallestField(x2); if IsInternalRep(y1) then if IsInternalRep(y2) then
return y1<y2; fi;
return true; elif IsInternalRep(y2) then
return false; fi; if IsModulusRep(y1) then if IsModulusRep(y2) then
return y1<y2; fi;
return true; elif IsModulusRep(y2) then
return false; fi;
d1 := y1![2];
d2 := y2![2]; if d1 < d2 then
return true; elif d1 > d2 then
return false; fi;
return y1![1] < y2![1]; end);
InstallMethod(\<,
IsIdenticalObj,
[ IsCoeffsModConwayPolRep,
IsFFE and IsInternalRep ], function(x1,x2)
local y1;
y1 := FFECONWAY.WriteOverSmallestField(x1); if not IsInternalRep(y1) then
return false; else
return y1 < x2; fi; end);
InstallMethod(\<,
IsIdenticalObj,
[ IsFFE and IsInternalRep,
IsCoeffsModConwayPolRep],
function(x1,x2)
local y2;
y2 := FFECONWAY.WriteOverSmallestField(x2); if not IsInternalRep(y2) then
return true; else
return x1 < y2; fi; end);
InstallMethod(\<,
IsIdenticalObj,
[ IsCoeffsModConwayPolRep,
IsFFE and IsModulusRep ], function(x1,x2)
local y1;
y1 := FFECONWAY.WriteOverSmallestField(x1); if not IsModulusRep(y1) then
return false; else
return y1 < x2; fi; end);
InstallMethod(\<,
IsIdenticalObj,
[ IsFFE and IsModulusRep,
IsCoeffsModConwayPolRep],
function(x1,x2)
local y2;
y2 := FFECONWAY.WriteOverSmallestField(x2); if not IsModulusRep(y2) then
return true; else
return x1 < y2; fi; end);
InstallMethod(IntFFE,
[IsFFE and IsCoeffsModConwayPolRep], function(x)
local i; for i in [2..Length(x![1])] do if not IsZero(x![1][i]) then
Error("IntFFE: element must lie in prime field"); fi;
od;
return IntFFE(x![1][1]); end);
InstallMethod( LogFFE,
IsIdenticalObj,
[IsFFE and IsCoeffsModConwayPolRep, IsFFE and IsCoeffsModConwayPolRep],
DoDLog );
InstallMethod( LogFFE,
IsIdenticalObj,
[IsFFE and IsInternalRep, IsFFE and IsCoeffsModConwayPolRep],
DoDLog );
InstallMethod( LogFFE,
IsIdenticalObj,
[ IsFFE and IsCoeffsModConwayPolRep, IsFFE and IsInternalRep],
DoDLog );
############################################################################# ## #M LargeGaloisField(p,d) -- construct GFs in this size range ## try next method if it goes wrong, to avoid dependency on ## method selection sequence. ## ## Cache fields in the family. ## Assuming we came via GF we have already passed a cache for last case called ##
InstallMethod( LargeGaloisField,
[IsPosInt, IsPosInt], function(p,d)
local fam; if not IsPrimeInt(p) then
Error("LargeGaloisField: Characteristic must be prime"); fi; if d =1 or p^d <= MAXSIZE_GF_INTERNAL then
TryNextMethod(); fi;
fam := FFEFamily(p); if not IsBound(fam!.ConwayFieldCache) then
fam!.ConwayFieldCache := []; fi; if not IsBound(fam!.ConwayFieldCache[d]) then
fam!.ConwayFieldCache[d] := FieldByGenerators(GF(p,1),[FFECONWAY.ZNC(p,d)]); fi;
return fam!.ConwayFieldCache[d]; end);
############################################################################# ## #M PrimitiveRoot for Galois fields ##
InstallMethod(PrimitiveRoot,
[IsField and IsFFECollection and IsFinite], function(f)
local p, d;
p := Characteristic(f);
d := DegreeOverPrimeField(f); if d > 1 and p^d > MAXSIZE_GF_INTERNAL then
return FFECONWAY.ZNC(p,d); else
TryNextMethod(); fi; end);
############################################################################# ## #M Coefficients of an element wrt the canonical basis -- are stored in the ## element
InstallMethod(Coefficients, "for a FFE in Conway polynomial representation wrt the canonical basis of its natural field",
IsCollsElms,
[IsCanonicalBasis and IsBasisFiniteFieldRep, IsFFE and IsCoeffsModConwayPolRep], function(cb,x) if not IsPrimeField(LeftActingDomain(UnderlyingLeftModule(cb))) then
TryNextMethod(); fi; if DegreeOverPrimeField(UnderlyingLeftModule(cb)) <> x![2] then
TryNextMethod(); fi;
PadCoeffs(x![1],x![2]);
return Immutable(x![1]); end);
############################################################################# ## #M Enumerator -- for a GF -- use an Enumerator for the equivalent rowspace ## ## when looking up elements, we may have to promote them to the right field
InstallMethod(Enumerator,
[IsField and IsFinite and IsFFECollection], function(f)
local p, fam, d, e, x; if Size(f) <= MAXSIZE_GF_INTERNAL then
TryNextMethod(); fi;
p := Characteristic(f);
fam := FFEFamily(p);
d := DegreeOverPrimeField(f); if d = 1then TryNextMethod(); fi;
e := Enumerator(RowSpace(GF(p,1),d));
return EnumeratorByFunctions(f, rec(
ElementNumber := function(en,n)
return Objectify(fam!.ConwayFldEltDefaultType, [ e[n], d, fail]); end,
NumberElement := function(en,x)
x := FFECONWAY.WriteOverLargerField(x,d);
return Position(e,x![1]); end)); end);
############################################################################# ## #M AsList, Iterator ## ## since we have a really efficient Enumerator method, lets use it.
InstallMethod(AsList,
[IsField and IsFinite and IsFFECollection], function(f) if Size(f) <= MAXSIZE_GF_INTERNAL then
TryNextMethod(); fi;
return AsList(Enumerator(f)); end);
InstallMethod(Iterator,
[IsField and IsFinite and IsFFECollection], function(f) if Size(f) <= MAXSIZE_GF_INTERNAL then
TryNextMethod(); fi;
return IteratorList(Enumerator(f)); end);
############################################################################# ## #M Random -- use Rowspace ##
InstallMethodWithRandomSource( Random, "for a random source and a large non-prime finite field",
[IsRandomSource, IsField and IsFFECollection and IsFinite], function(rs, f)
local d, p, v, fam; if Size(f) <= MAXSIZE_GF_INTERNAL then
TryNextMethod(); fi; if IsPrimeField(f) then
TryNextMethod(); fi;
d := DegreeOverPrimeField(f);
p := Characteristic(f);
v := Random(rs, RowSpace(GF(p,1),d));
fam := FFEFamily(Characteristic(f));
return Objectify(fam!.ConwayFldEltDefaultType, [v,d,fail]); end);
InstallMethod(MinimalPolynomial,
IsCollsElmsX,
[IsPrimeField, IsCoeffsModConwayPolRep and IsFFE, IsPosInt], function(fld, elm, ind)
local fam, d, dd, x, y, p, o, m, i, r;
fam := FamilyObj(elm);
d := DegreeFFE(elm);
dd := elm![2];
x := elm![1];
y := x;
p := Characteristic(elm);
o := ListWithIdenticalEntries(dd,Z(p)*0);
o[1] := Z(p)^0;
ConvertToVectorRep(o,p);
m := [o,y]; for i in [2..d] do
y := ProductCoeffs(y,x);
fam!.ConwayFldEltReducers[dd](y);
Add(m,y);
od;
ConvertToMatrixRep(m,p);
r := SemiEchelonMatTransformation(m);
Assert(1, Length(r.relations) = 1);
return UnivariatePolynomialByCoefficients(fam, r.relations[1],ind); end);
############################################################################# ## #M Display for matrix of ffes ##
InstallMethod( Display, "for matrix of FFEs (for larger fields)",
[ IsFFECollColl and IsMatrix ], 10, # prefer this to existing method function(m)
local deg, chr, d, w, r, dr, x, s, y, j, a; if Length(m) = 0 or Length(m[1])= 0then
TryNextMethod(); fi;
deg := Lcm( List( m, DegreeFFE ) );
chr := Characteristic(m[1,1]); if deg = 1 or chr^deg <= MAXSIZE_GF_INTERNAL then
TryNextMethod(); fi;
Print("z = Z( ",chr,", ",deg,"); z2 = z^2, etc.\n");
d := [];
w := 1; for r in m do
dr := []; for x in r do if IsZero(x) then
Add(dr,"."); else
s := "";
y := FFECONWAY.WriteOverLargerField(x,deg); for j in [0..deg-1] do
a := IntFFE(y![1][j+1]); if a <> 0then if Length(s) <> 0then
Append(s,"+"); fi; if a = 1 and j = 0then
Append(s,"1"); else if a <> 1then
Append(s,String(a)); fi; if j <> 0then
Append(s,"z"); if j <> 1then
Append(s,String(j)); fi; fi; fi; fi;
od;
Add(dr,s); if Length(s) > w then
w := Length(s); fi; fi;
od;
Add(d,dr);
od; for dr in d do for s in dr do
Print(String(s,-w-1));
od;
Print("\n");
od; end);
FFECONWAY.WriteOverSmallestCommonField := function(v)
local d, degs, p, x, dx, i;
d := 1;
degs := [];
p := Characteristic(v[1]); for x in v do if not IsFFE(x) or Characteristic(x) <> p then
return fail; fi;
dx := DegreeFFE(x);
Add(degs, dx);
od;
d := Lcm(Set(degs)); for i in [1..Length(v)] do if IsCoeffsModConwayPolRep(v[i]) then if d < v[i]![2] then
v[i] := FFECONWAY.TryToWriteInSmallerField(v[i],d); elif d > v[i]![2] then
v[i] := FFECONWAY.WriteOverLargerField(v[i],d); fi; fi;
od;
return p^d; end;
############################################################################# ## #M AsInternalFFE( <conway ffe> ) ##
InstallMethod( AsInternalFFE, [IsFFE and IsCoeffsModConwayPolRep], function (x)
local y;
y := FFECONWAY.WriteOverSmallestField(x); if IsInternalRep(y) then
return y; else
return fail; fi; end);
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.