############################################################################# ## ## This file is part of GAP, a system for computational discrete algebra. ## This file's authors include Frank Celler. ## ## 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 ## ## The '<Something>RowVector' functions operate on row vectors, that is to ## say (where it makes sense) that the vectors must have the same length, ## for example 'AddRowVector' requires that the two involved row vectors ## have the same length. ## ## The '<DoSomething>Coeffs' functions operate on row vectors which might ## have different lengths. They will return the new length without counting ## trailing zeros, however they will *not* necessarily remove this trailing ## zeros. The only exception to this rule is 'RemoveOuterCoeffs' which ## returns the number of elements removed at the beginning. ## ## The '<Something>Coeffs' functions operate on row vectors which might have ## different lengths, the returned result will have trailing zeros removed. ##
############################################################################# ## #M AddRowVector( <list1>, <list2>, <mult>, <from>, <to> ) ##
InstallMethod( AddRowVector, "kernel method for plain lists of cyclotomics",
IsCollsCollsElmsXX,
[ IsSmallList and IsDenseList and IsMutable and
IsCyclotomicCollection and IsPlistRep,
IsDenseList and IsCyclotomicCollection and IsPlistRep,
IsCyclotomic,
IsPosInt,
IsPosInt ], 0,
ADD_ROW_VECTOR_5_FAST
);
InstallMethod( AddRowVector, "kernel method for small lists",
IsCollsCollsElmsXX,
[ IsSmallList and IsDenseList and IsMutable,
IsDenseList,
IsMultiplicativeElement,
IsPosInt,
IsPosInt ], 0,
ADD_ROW_VECTOR_5
);
InstallMethod( AddRowVector, "generic method",
IsCollsCollsElmsXX,
[ IsDenseList and IsMutable,
IsDenseList,
IsMultiplicativeElement,
IsPosInt,
IsPosInt ], 0, function( l1, l2, m, f, t )
local i;
for i in [ f .. t ] do
l1[i] := l1[i] + m * l2[i];
od; end
);
BindGlobal( "L1_IMMUTABLE_ERROR", function(arg) if IsMutable(arg[1]) then
TryNextMethod(); else
Error("arg[1] must be mutable"); fi; end );
InstallOtherMethod( AddRowVector,"error if immutable",true,
[ IsList,IsObject,IsObject,IsPosInt,IsPosInt],0,
L1_IMMUTABLE_ERROR);
############################################################################# ## #M AddRowVector( <list1>, <list2>, <mult> ) ##
InstallOtherMethod( AddRowVector, "kernel method for plain lists of cyclotomics(3 args)",
IsCollsCollsElms,
[ IsSmallList and IsDenseList and IsMutable and IsCyclotomicCollection
and IsPlistRep,
IsDenseList and IsPlistRep and IsCyclotomicCollection,
IsCyclotomic ], 0,
ADD_ROW_VECTOR_3_FAST );
InstallOtherMethod( AddRowVector, "kernel method for small lists (3 args)",
IsCollsCollsElms,
[ IsSmallList and IsDenseList and IsMutable,
IsDenseList,
IsMultiplicativeElement ], 0,
ADD_ROW_VECTOR_3 );
InstallOtherMethod( AddRowVector, "kernel method for GF2 (3 args)",
IsCollsCollsElms,
[ IsGF2VectorRep and IsMutable,
IsGF2VectorRep,
IS_FFE and IsInternalRep ],0,
ADDCOEFFS_GF2VEC_GF2VEC_MULT );
InstallOtherMethod( AddRowVector, "kernel method for vecffe (5 args -- ignores last 2)",
IsCollsCollsElmsXX,
[ IsRowVector and IsMutable and IsPlistRep and IsFFECollection,
IsRowVector and IsPlistRep and IsFFECollection,
IS_FFE and IsInternalRep, IsPosInt, IsPosInt ],0, function( sum, vec, mult, from, to)
AddRowVector(sum,vec,mult); end);
InstallOtherMethod( AddRowVector, "kernel method for vecffe (3 args)",
IsCollsCollsElms,
[ IsRowVector and IsMutable and IsPlistRep and IsFFECollection,
IsRowVector and IsPlistRep and IsFFECollection,
IS_FFE and IsInternalRep ],0,
ADD_ROWVECTOR_VECFFES_3 );
InstallOtherMethod( AddRowVector, "generic method 3 args",
IsCollsCollsElms,
[ IsDenseList and IsMutable,
IsDenseList,
IsMultiplicativeElement ], 0, function( l1, l2, m )
local i; for i in [ 1 .. Length(l1) ] do
l1[i] := l1[i] + m * l2[i];
od; end );
InstallOtherMethod( AddRowVector,"error if immutable",true,
[ IsList,IsObject,IsObject],0,L1_IMMUTABLE_ERROR);
InstallOtherMethod( AddRowVector, "do nothing if mult is zero",
IsCollsCollsElms,
[ IsList, IsObject, IsObject and IsZero],
SUM_FLAGS, #can't do better
ReturnTrue);
############################################################################# ## #M AddRowVector( <list1>, <list2> ) ##
InstallOtherMethod( AddRowVector, "kernel method for plain lists of cyclotomics (2 args)",
IsIdenticalObj,
[ IsSmallList and IsDenseList and IsMutable and
IsCyclotomicCollection and IsPlistRep,
IsDenseList and IsCyclotomicCollection and IsPlistRep ], 0,
ADD_ROW_VECTOR_2_FAST
);
InstallOtherMethod( AddRowVector, "kernel method for GF2 (2 args)",
IsIdenticalObj,
[ IsGF2VectorRep and IsMutable and IsRowVector,
IsGF2VectorRep and IsRowVector],0,
ADDCOEFFS_GF2VEC_GF2VEC );
InstallOtherMethod( AddRowVector, "kernel method for vecffe (2 args)",
IsIdenticalObj,
[ IsRowVector and IsMutable and IsPlistRep and IsFFECollection,
IsRowVector and IsPlistRep and IsFFECollection],0,
ADD_ROWVECTOR_VECFFES_2 );
InstallOtherMethod( AddRowVector, "generic method (2 args)",
IsIdenticalObj, [ IsDenseList and IsMutable, IsDenseList ], 0, function( l1, l2 )
local i; for i in [ 1 .. Length(l1) ] do
l1[i] := l1[i] + l2[i];
od; end );
InstallOtherMethod( AddRowVector, "kernel method for small lists (2 args)",
IsIdenticalObj,
[ IsSmallList and IsDenseList and IsMutable,
IsDenseList ], 0,
ADD_ROW_VECTOR_2);
InstallOtherMethod( AddRowVector, "kernel method for GF2 (2 args)",
IsIdenticalObj,
[ IsGF2VectorRep and IsMutable,
IsGF2VectorRep],0,
ADDCOEFFS_GF2VEC_GF2VEC );
InstallOtherMethod( AddRowVector,"error if immutable",true,
[ IsList,IsObject],0,
L1_IMMUTABLE_ERROR);
############################################################################# ## #M MultVectorLeft( <list>, <mul> ) ##
InstallMethod( MultVectorLeft, "for a mutable dense list, and an object",
[ IsDenseList and IsMutable,
IsObject ], function( l, m )
local i; for i in [ 1 .. Length(l) ] do
l[i] := m * l[i];
od; end );
InstallOtherMethod( MultVectorLeft, "error if immutable",
[ IsList, IsObject ],
L1_IMMUTABLE_ERROR);
InstallMethod( MultVectorLeft, "kernel method for a mutable dense small list, and an object",
IsCollsElms,
[ IsSmallList and IsDenseList and IsMutable,
IsObject ],
MULT_VECTOR_LEFT_2
);
InstallMethod( MultVectorLeft, "kernel method for a mutable dense plain list of \
cyclotomics, and a cyclotomic",
IsCollsElms,
[ IsDenseList and IsMutable and IsPlistRep and IsCyclotomicCollection,
IsCyclotomic ],
MULT_VECTOR_2_FAST
);
InstallMethod( MultVectorLeft, "kernel method for a mutable row vector of ffes in \
plain list rep, and an ffe",
IsCollsElms,
[ IsRowVector and IsMutable and IsPlistRep and IsFFECollection,
IsFFE],0,
MULT_VECTOR_VECFFES );
InstallMethod(PadCoeffs, "pad with supplied value",
IsCollsXElms,
[IsList and IsMutable, IsPosInt, IsObject], function(l,n,x)
local len, i;
len := Length(l); for i in [len+1..n] do
l[i] := x;
od;
return; end);
InstallMethod(PadCoeffs, "pad with zero",
[IsList and IsMutable and IsAdditiveElementWithZeroCollection,
IsPosInt], function(l,n)
local len, z, i;
len := Length(l); if len = 0then
Error("Don't know what to pad with"); fi;
z := Zero(l[1]); for i in [len+1..n] do
l[i] := z;
od;
return; end);
if Length(p1) <> Length(p2) then
Error( "positions lists have different lengths" ); fi; for i in [ 1 .. Length(p1) ] do if not IsBound(l1[p1[i]]) then
l1[p1[i]] := m*l2[p2[i]]; else
l1[p1[i]] := l1[p1[i]] + m*l2[p2[i]]; fi;
od; if0 < Length(l1) then
zero := Zero(l1[1]);
n1 := Length(l1); while0 < n1 and l1[n1] = zero do
n1 := n1 - 1;
od; else
n1 := 0; fi;
return n1; end );
InstallOtherMethod( AddCoeffs,"error if immutable", true,
[ IsList,IsObject,IsObject,IsObject,IsObject],0,
L1_IMMUTABLE_ERROR);
############################################################################# ## #M AddCoeffs( <list1>, <list2> ) ##
InstallOtherMethod( AddCoeffs, "generic method (2nd arg empty)", true,
[ IsDenseList and IsMutable, IsList and IsEmpty], 0, function( l1, l2 )
local len, zero; if0 = Length(l1) then
return 0; else
len := Length(l1);
zero := Zero(l1[1]); while0 < len and l1[len] = zero do
len := len - 1;
od;
return len; fi; end );
InstallOtherMethod( AddCoeffs,"error if immutable", true,
[ IsList,IsObject],0,
L1_IMMUTABLE_ERROR);
function( l1, l2, n2, l3, n3 )
local zero, i, z, j, n1;
# catch the trivial cases if n2 = 0then
return 0; elif n3 = 0then
return 0; fi;
zero := Zero(l2[1]); if IsIdenticalObj( l1, l2 ) then
l2 := ShallowCopy(l2); elif IsIdenticalObj( l1, l3 ) then
l3 := ShallowCopy(l3); fi;
# fold the product for i in [ 1 .. n2+n3-1 ] do
z := zero; for j in [ Maximum(i+1-n3,1) .. Minimum(n2,i) ] do
z := z + l2[j]*l3[i+1-j];
od;
l1[i] := z;
od;
# return the length of <l1>
n1 := n2+n3-1; while0 < n1 and l1[n1] = zero do
n1 := n1 - 1;
od;
return n1;
end );
InstallOtherMethod( MultCoeffs,"error if immutable", true,
[ IsList,IsObject,IsInt,IsObject,IsInt],0,
L1_IMMUTABLE_ERROR);
# catch trivial cases if0 = n2 then
Error( "<l2> must be non-zero" ); elif0 = n1 then
return n1; fi;
zero := Zero(l1[1]); while0 < n2 and l2[n2] = zero do
n2 := n2 - 1;
od; if0 = n2 then
Error( "<l2> must be non-zero" ); fi; while0 < n1 and l1[n1] = zero do
n1 := n1 - 1;
od;
# reduce coeffs while n1 >= n2 do
q := -l1[n1]/l2[n2];
l := n1-n2; for i in [ n1-n2+1 .. n1 ] do
l1[i] := l1[i]+q*l2[i-n1+n2]; if l1[i] <> zero then
l := i; fi;
od;
n1 := l;
od;
return n1; end );
InstallOtherMethod( ReduceCoeffs,"error if immutable", true,
[ IsList,IsInt,IsObject,IsInt],0,
L1_IMMUTABLE_ERROR);
InstallOtherMethod( ReduceCoeffs,"error if immutable", true,
[ IsList,IsObject],0,
L1_IMMUTABLE_ERROR);
############################################################################# ## #M ReduceCoeffsMod( <list1>, <len1>, <list2>, <len2>, <mod> ) ##
InstallMethod( ReduceCoeffsMod,"generic method (5 args)", true,
[ IsDenseList and IsMutable, IsInt, IsDenseList, IsInt, IsInt ], 0, function( l1, n1, l2, n2, p )
local zero, l, q, i;
# catch trivial cases if0 = n2 then
Error( "<l2> must be non-zero" ); elif0 = n1 then
return l1; fi;
zero := Zero(l1[1]); while0 < n2 and l2[n2] = zero do
n2 := n2 - 1;
od; if0 = n2 then
Error( "<l2> must be non-zero" ); fi; while0 < n2 and l1[n1] = zero do
n1 := n1 - 1;
od;
# reduce coeffs while n1 >= n2 do
q := -l1[n1]/l2[n2] mod p;
l := n1-n2; for i in [ n1-n2+1 .. n1 ] do
l1[i] := (l1[i]+q*l2[i-n1+n2] mod p) mod p; if l1[i] <> zero then
l := i; fi;
od;
n1 := l;
od;
return n1; end );
InstallOtherMethod( ReduceCoeffsMod,"error if immutable", true,
[ IsList,IsInt,IsObject,IsInt,IsInt],0,
L1_IMMUTABLE_ERROR);
############################################################################# ## #M ReduceCoeffsMod( <list1>, <list2>, <mod> ) ##
InstallOtherMethod( ReduceCoeffsMod,"generic: list,list,int", true,
[ IsDenseList and IsMutable, IsDenseList, IsInt ], 0, function( l1, l2, p )
return ReduceCoeffsMod( l1, Length(l1), l2, Length(l2), p ); end );
InstallOtherMethod( ReduceCoeffsMod,"error if immutable", true,
[ IsList,IsObject,IsInt],0,
L1_IMMUTABLE_ERROR);
# catch trivial cases if0 = n2 then
Error( "<l2> must be non-zero" ); elif0 = n1 then
return [[],[]]; fi;
zero := Zero(l1[1]); while0 < n2 and l2[n2] = zero do
n2 := n2 - 1;
od; if0 = n2 then
Error( "<l2> must be non-zero" ); fi; while0 < n1 and l1[n1] = zero do
n1 := n1 - 1;
od;
rem := l1{[1..n1]};
quot := ListWithIdenticalEntries(n1-n2+1,zero); # reduce coeffs while n1 >= n2 do
q := rem[n1]/l2[n2];
l := n1-n2;
quot[l+1] := q; for i in [ n1-n2+1 .. n1 ] do
rem[i] := rem[i]-q*l2[i-n1+n2]; if rem[i] <> zero then
l := i; fi;
od;
n1 := l;
od;
return [quot,rem]; end );
############################################################################# ## #M QuotRemCoeffs( <list1>, <list2> ) ##
InstallOtherMethod( QuotRemCoeffs,"generic, use list lengths",
true,
[ IsDenseList,
IsDenseList ], 0,
############################################################################# ## #F ValuePol( <coeffs_f>, <x> ) . . . . . . evaluate a polynomial at a point ##
InstallMethod( ValuePol,"generic",true,[IsList,IsRingElement],0, function( f, x )
local value, i, id;
id := x ^ 0;
value := 0 * id;
i := Length(f); while0 < i do
value := value * x + id * f[i];
i := i-1;
od;
return value; end );
InstallMethod( ValuePol,"special code for rational values",true,
[IsList,IsRat],0, function( f, x )
local value, i;
value := 0 * x;
i := Length(f); while0 < i do
value := value * x + f[i];
i := i-1;
od;
return value; end );
############################################################################# ## #F QuotRemPolList( <f>, <g>) ## ## Quotient and Remainder of polynomials given as list, is needed for ## algebraic extensions and fits best here. ##
BindGlobal( "QuotRemPolList", function(f,g)
local q,m,n,i,c,k,z;
q:=[];
f:=ShallowCopy(f);
g:=ShallowCopy(g);
z:=0*g[1];
n:=Length(g); while n>0 and g[n]=z do
Unbind(g[n]);
n:=n-1;
od;
n:=Length(g);
m:=Length(f); for i in [0..(m-n)] do
c:=f[m-i]/g[n];
q[m-n-i+1]:=c; for k in [1..n] do
f[m-i-n+k]:=f[m-i-n+k]-c*g[k];
od;
od;
return [q,f]; end );
############################################################################# ## #M WeightVecFFE( <vec> ) ##
InstallMethod(WeightVecFFE,"generic",true,[IsList],0, function(v)
local z,i,n;
z:=Zero(v[1]);
n:=0; for i in [1..Length(v)] do if v[i]<>z then n:=n+1;fi;
od;
return n; end);
InstallMethod(WeightVecFFE,"gf2 vectors",true,[IsGF2VectorRep and IsList],0, function(a)
return DIST_GF2VEC_GF2VEC(a,Zero(a)); end);
############################################################################# ## #M DistanceVecFFE( <vec1>,<vec2> ) ##
InstallMethod(DistanceVecFFE,"generic",IsIdenticalObj,[IsList,IsList],0, function(v,w)
local i,n;
n:=0; for i in [1..Length(v)] do if v[i]<>w[i] then n:=n+1;fi;
od;
return n; end);
InstallMethod(DistanceVecFFE,"gf2 vectors",
IsIdenticalObj,[IsGF2VectorRep and IsList,IsGF2VectorRep and IsList], 0, DIST_GF2VEC_GF2VEC);
############################################################################# ## #M DistancesDistributionVecFFEsVecFFE( <vecs>,<vec> ) ##
InstallMethod(DistancesDistributionVecFFEsVecFFE,"generic",IsCollsElms,
[IsList, IsList],0, function(vecs,vec)
local d,i;
ConvertToMatrixRep(vecs);
ConvertToVectorRep(vec);
d:=ListWithIdenticalEntries(Length(vec)+1,0); for i in vecs do
i:=DistanceVecFFE(i,vec);
d[i+1]:=d[i+1]+1;
od;
return d; end);
############################################################################# ## #M DistancesDistributionMatFFEsVecFFE( <vecs>,<vec> ) ##
DeclareGlobalName("DistVecClosVecLib");
BindGlobal( "DistVecClosVecLib", function(veclis,vec,d,sum,pos,l,m)
local i,di,vp;
vp:=veclis[pos]; for i in [0..m] do if pos<l then
DistVecClosVecLib(veclis,vec,d,sum,pos+1,l,m); else
di:=DistanceVecFFE(sum,vec);
d[di+1]:=d[di+1]+1; fi;
AddRowVector(sum,vp[i+1]);
od; end );
InstallMethod(DistancesDistributionMatFFEVecFFE,"generic",IsCollsElmsElms,
[IsMatrix,IsFFECollection and IsField, IsList],0, function(mat,f,vec)
local d,fdi,i,j,veclis,mult,mults,fdip,q, ok8;
ConvertToMatrixRepNC(mat,f);
ConvertToVectorRepNC(vec,f); # build the data structures
f:=AsSSortedList(f);
Assert(1,IsZero(f[1]));
# get differences between field entries (so we can get the next vector # with one addition)
fdi:=[]; for j in [2..Length(f)] do
fdi[j-1]:=f[j]-f[j-1];
od;
Add(fdi,-Last(f)); # the subtraction multiple we need at the end.
fdip := List(fdi, x-> Position(fdi,x));
# veclis contains for each vector in mat a list of its fdi-multiples. # using this list we do not need any scalar arithmetic in the loops below.
veclis:=[]; for i in mat do
mults:=[];
mults[Length(fdi)+1]:=false; # force plist and not matrix rep. for j in [1..Length(fdi)] do if fdip[j] < j then
mult := mults[fdip[j]]; else
mult:=fdi[j]*i; # vector times difference fi;
mults[j]:=mult;
od;
Add(veclis,mults);
od;
d:=ListWithIdenticalEntries(Length(vec)+1,0);
q := Length(f); if q = 2then # gf2 case # zero out trailing bits. # This is not time relevant and easier to do in # the library by calling kernel functions # which do it as a side effect.
for i in veclis do for j in i{[1..Length(i)-1]} do
DIST_GF2VEC_GF2VEC(j,j);
od;
od;
DIST_VEC_CLOS_VEC(veclis,vec,d);
return d; elif q <= 256then # # 8 bit case, have to get everything over one field! #
ok8 := true; for i in veclis do for j in [1..q] do if q <> ConvertToVectorRepNC(i[j],q) then
i[j] := PlainListCopy(i[j]);
MakeImmutable(i[j]); if q <> ConvertToVectorRepNC(i[j],q) then
ok8 := false; fi; fi;
od;
od; if q <> ConvertToVectorRepNC(vec,q) then
vec := PlainListCopy(vec);
MakeImmutable(vec); if q <> ConvertToVectorRepNC(vec,q) then
ok8 := false; fi; fi;
if ok8 then
DISTANCE_DISTRIB_VEC8BITS( veclis, vec, d);
return d; fi; fi;
# no kernel method available, use library recursion
DistVecClosVecLib(veclis,vec,d,
ZeroOp(vec),1,Length(veclis),
Length(veclis[1])-2# -2: last entry is `false', # entry -1 the negative
);
DeclareGlobalName("AClosVecLib");
BindGlobal( "AClosVecLib", function(veclis,vec,sum,pos,l,m,cnt,stop,bd,bv,coords,bcoords)
local i,di,vp; if# if this vector has coeff 0 there must be at least cnt+1 free positions # to come up with the right number of vectors
(l>cnt+pos) then
bd:=AClosVecLib(veclis,vec,sum,pos+1,l,m,cnt,stop,bd,bv,coords,bcoords);
if bd<=stop then
return bd; fi; fi;
vp:=veclis[pos]; for i in [1..m] do
AddRowVector(sum,vp[i]); if coords <> false then
coords[pos] := i; fi; if cnt = 0then # test this vector
di:=DistanceVecFFE(sum,vec); if di<bd then # store new optimum
bd:=di;
bv{[1..Length(sum)]}:=sum; if coords <> false then
bcoords{[1..Length(veclis)]} := coords; fi; if bd <= stop then
return bd; fi; fi; else if pos<l then
bd:=AClosVecLib(veclis,vec,sum,pos+1,l,m,cnt-1,stop,bd,bv,coords,bcoords); if bd<=stop then
return bd; fi; fi; fi;
od; # reset component to 0
AddRowVector(sum,vp[m+1]);
coords[pos] := 0;
return bd; end );
BindGlobal( "AClosestVectorDriver", function(mat,f,vec,cnt,stop,coords)
local b,fdi,i,j,veclis,mult,mults,fdip, q, ok8,c,bc;
# special case: combination of 0 vectors if cnt=0then if coords then
return [Zero(vec),ListWithIdenticalEntries(Length(mat),Zero(f))]; else
return Zero(vec); fi; fi;
if cnt > Length(mat) then
Error("First list needs at least ", cnt, " vectors . . .\n"); fi;
# build the data structures
f:=AsSSortedList(f);
q := Length(f);
Assert(1,IsZero(f[1]));
# get differences between field entries (so we can get the next vector # with one addition)
fdi:=[]; for j in [2..q] do
fdi[j-1]:=f[j]-f[j-1];
od;
Add(fdi,-Last(f)); # the subtraction multiple we need at the end.
fdip := List(fdi, x-> Position(fdi,x));
# veclis contains for each vector in mat a list of its fdi-multiples. # using this list we do not need any scalar arithmetic in the loops below.
veclis:=[]; for i in mat do
mults:=[];
mults[Length(fdi)+1]:=false; # force plist and not matrix rep. for j in [1..Length(fdi)] do if fdip[j] < j then
mult := mults[fdip[j]]; #reuse else
mult:=fdi[j]*i; # vector times difference fi;
mults[j]:=mult;
od;
Add(veclis,mults);
od;
if q = 2then # gf2 case # zero out trailing bits. This is not time relevant and easier to do in # the library by calling kernel functions which do it as a side effect. for i in veclis do for j in i{[1..Length(i)-1]} do
DIST_GF2VEC_GF2VEC(j,j);
od;
od; if coords then
b := A_CLOS_VEC_COORDS(veclis,vec,cnt-1,stop);
ConvertToVectorRepNC(b[1],2);
b[2] := f{1+b[2]}; else
b:=A_CLOS_VEC(veclis,vec,cnt-1,stop);
ConvertToVectorRepNC(b,2); fi;
return b; elif q <= 256then # # 8 bit case, have to get everything over one field! #
ok8 := true; for i in veclis do for j in [1..q] do if q <> ConvertToVectorRepNC(i[j],q) then
i[j] := PlainListCopy(i[j]);
MakeImmutable(i[j]); if q <> ConvertToVectorRepNC(i[j],q) then
ok8 := false; fi; fi;
od;
od; if q <> ConvertToVectorRepNC(vec,q) then
vec := PlainListCopy(vec);
MakeImmutable(vec); if q <> ConvertToVectorRepNC(vec,q) then
ok8 := false; fi; fi;
if ok8 then if coords then
b := A_CLOSEST_VEC8BIT_COORDS(veclis,vec,cnt-1,stop);
b[2] := f{1+b[2]}; else
return A_CLOSEST_VEC8BIT(veclis, vec, cnt-1, stop); fi; fi; fi; # no kernel method available, use library recursion
b:=ListWithIdenticalEntries(Length(vec),0); if coords then
c := ListWithIdenticalEntries(Length(mat),0);
bc:= ListWithIdenticalEntries(Length(mat),0);
AClosVecLib(veclis,vec,ZeroOp(vec),1,Length(veclis),
Length(f)-1,
cnt-1, # the routine uses 0 offset
stop,
Length(b)+1, # value 1 larger than worst
b, c, bc);
ConvertToVectorRepNC(b);
return [b,f{1+bc}]; else
AClosVecLib(veclis,vec,ZeroOp(vec),1,Length(veclis),
Length(f)-1,
cnt-1, # the routine uses 0 offset
stop,
Length(b)+1, # value 1 larger than worst
b, false,false);
ConvertToVectorRepNC(b);
return b; fi; end );
InstallMethod(AClosestVectorCombinationsMatFFEVecFFE,"generic", function(a,b,c,d,e)
return HasElementsFamily(a) and IsIdenticalObj(b,c)
and IsIdenticalObj(ElementsFamily(a),b); end,
[IsMatrix,IsFFECollection and IsField, IsList, IsInt,IsInt],0, function(mat,f,vec,cnt,stop)
return AClosestVectorDriver(mat,f,vec,cnt,stop,false); end);
InstallMethod(AClosestVectorCombinationsMatFFEVecFFECoords,"generic", function(a,b,c,d,e)
return HasElementsFamily(a) and IsIdenticalObj(b,c)
and IsIdenticalObj(ElementsFamily(a),b); end,
[IsMatrix,IsFFECollection and IsField, IsList, IsInt,IsInt],0, function(mat,f,vec,cnt,stop)
return AClosestVectorDriver(mat,f,vec,cnt,stop,true); end);
############################################################################# ## #M CosetLeadersMatFFE( <mat>,<f> ) ## ## returns a list of representatives of minimal weight for the cosets of ## the vector space generated by the rows of <mat> over the finite field ## <f>. All rows of <mat> must have the same length, and all elements must ## lie in <f>. The rows of <mat> must be linearly independent. ##
DeclareGlobalName("CosetLeadersInner");
BindGlobal( "CosetLeadersInner", function(vl, v, w, weight, pos, record, felts,q, tofind)
local found, i, j;
found := 0;
# if just one more vector is needed, then shift to a loop # to avoid recursion overhead if weight = 1then for j in [pos..Length(v)] do # add it
AddRowVector(w, vl[j][1]);
v[j] := felts[2]; # deal with the result
found := found + record(w,v); if found = tofind then
return found; fi; # and clean it off
AddRowVector(w, vl[j][q+1]);
v[j] := felts[1];
od; else
# option 1, do nothing in position pos if Length(v) >= pos + weight then
found := found + CosetLeadersInner( vl, v, w, weight, pos+1,
record, felts,q, tofind); if found = tofind then
return found; fi; fi;
# option 2, add each multiple and recurse for i in [1..q-1] do
AddRowVector(w, vl[pos][i]);
v[pos] := felts[i+1];
found := found + CosetLeadersInner( vl, v, w, weight -1,
pos +1, record, felts, q, tofind - found); if found = tofind then
return found; fi;
od;
AddRowVector(w, vl[pos][q]);
v[pos] := felts[1]; fi;
return found; end );
InstallMethod(CosetLeadersMatFFE,"generic",IsCollsElms,
[IsMatrix,IsFFECollection and IsField],0, function(mat,f)
local q, leaders, tofind, n,m, t, vl, i, felts, fds,
fdps, v,j,x, w, record, nzfelts, weight, ok8;
record := function(v,w)
local sy,x,u;
sy := NumberFFVector(v,q); if not IsBound(leaders[sy+1]) then for x in nzfelts do
sy := NumberFFVector(v*x,q);
u := w*x;
MakeImmutable(u);
leaders[sy+1] := u;
od;
return q-1; fi;
return 0; end;
q := Size(f);
n := Length(mat[1]);
m := Length(mat);
tofind := q^m;
t := TransposedMat(mat);
vl := [];
vl[m+1] := false;
felts := AsSSortedList(f);
Assert(2, felts[1] = Zero(f));
nzfelts := felts{[2..q]};
fds := List([2..q], i->felts[i] - felts[i-1]);
Add(fds, - Sum(fds));
Add(fds, - One(f));
fdps := List(fds, x-> Position(fds,x)); for i in [1..n] do
v := t[i];
vl[i] := []; for j in [1..q+1] do if fdps[j] < j then
Add(vl[i], vl[i][fdps[j]]); else
Add(vl[i], v*fds[j]); fi;
od;
Add(vl[i],false);
od;
v := ListWithIdenticalEntries(n, felts[1]);
w := ZeroOp(t[1]); if2 <= q and q < 256then
# 8 bit case, need to get all vectors over the right field
ok8 := true; if q <> ConvertToVectorRepNC(v,q) then
v := PlainListCopy(v);
ok8 := ok8 and q = ConvertToVectorRepNC(v,q); fi; if ok8 and q <> ConvertToVectorRepNC(w,q) then
w := PlainListCopy(w);
ok8 := ok8 and q = ConvertToVectorRepNC(w,q); fi; for x in vl{[1..n]} do for i in [1..q+1] do if ok8 and q <> ConvertToVectorRepNC(x[i],q) then
x[i] := PlainListCopy(x[i]);
ok8 := ok8 and q = ConvertToVectorRepNC(x[i],q); fi;
od;
od; else
ok8 := false; fi;
leaders := [Immutable(v)];
# this line checks that the required number of coset leaders # CAN be stored in a plain list
leaders[tofind+1] := false;
tofind := tofind -1;
weight := 0; while tofind > 0do
weight := weight + 1; if weight > n then
Error("not all cosets found"); fi; if q = 2then
tofind := tofind - COSET_LEADERS_INNER_GF2( vl, weight,
tofind, leaders); elif ok8 then
tofind := tofind - COSET_LEADERS_INNER_8BITS( vl, weight,
tofind, leaders, felts); else
tofind := tofind - CosetLeadersInner(vl, v, w, weight, 1,
record, felts, q, tofind); fi;
od;
Unbind(leaders[q^m+1]);
return leaders; end);
############################################################################# ## #M AddToListEntries( <list>, <poss>, <x> ) ## ## modifies <list> in place by adding <x> to each of the entries ## indexed by <poss>. ## ## kernel method for plain lists of cyclotomics, plain ranges and integers ##
InstallMethod( AddToListEntries, "fast kernel method", true,
[IsList and IsPlistRep and IsMutable and IsCyclotomicCollection,
IsRange and IsRangeRep, IsInt], 0,
ADD_TO_LIST_ENTRIES_PLIST_RANGE);
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.16Angebot
¤
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.