############################################################################# ## ## This file is part of GAP, a system for computational discrete algebra. ## This file's authors include Gene Cooperman, Scott Murray, Alexander Hulpke. ## ## 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 some hashfunctions for objects in the GAP library. ## This code was factored out from dict.gi to prevent cross dependencies ## between dict.gi and the rest of the library. ## #T * This is all apparently completely undocumented. #
InstallMethod(SparseIntKey,"defaults to DenseIntKey",true,[IsObject,IsObject], 0,DenseIntKey);
############################################################################# ## #F HashKeyBag(<obj>,<seed>,<skip>,<maxread>) #F HashKeyWholeBag(<obj>,<seed>) ## ## returns a hash key which is given by the bytes in the bag storing <obj>. ## The result is reduced modulo $2^{28}$ (on 32 bit systems) resp. modulo ## $2^{60}$ (on 64 bit systems) to obtain a small integer. ## As some objects carry excess data in their bag, the first <skip> bytes ## will be skipped and <maxread> bytes (a value of -1 represents infinity) ## will be read at most. (The proper values for these numbers might depend on ## the internal representation used as well as on the word length of the ## machine on which {\GAP} is running and care has to be taken when using ## `HashKeyBag' to ensure identical key values for equal objects.) ## ## The values returned by `HashKeyBag' are not guaranteed to be portable ## between different runs of {\GAP} and no reference to their absolute ## values ought to be made. ## ## HashKeyWholeBag hashes all the contents of a bag, which is equivalent ## to passing 0 and -1 as the third and fourth arguments of HashKeyBag. ## Be aware that for many types in GAP (for example permutations), equal ## objects may not have identical bags, so HashKeyWholeBag may return ## different values for two equal objects. ##
BindGlobal("HashKeyBag",HASHKEY_BAG);
BindGlobal("HashKeyWholeBag", {x,y} -> HASHKEY_BAG(x,y,0,-1));
############################################################################# ## #M SparseIntKey(<objcol>) ##
InstallMethod(SparseIntKey,"for finite Gaussian row spaces",true,
[ IsFFECollColl and IsGaussianRowSpace,IsObject ], 0, function(m,v)
local f,n,bytelen,data,qq,i,b,nn;
f:=LeftActingDomain(m);
n:=Size(f); if n=2then
bytelen:=QuoInt(Length(v),8); if bytelen<=8then # short GF2
return x->NumberFFVector(x,2); else # long GF2
data:=[2*GAPInfo.BytesPerVariable,bytelen];
return function(x) if not IsGF2VectorRep(x) then
Info(InfoWarning,1,"uncompressed vector");
x:=ShallowCopy(x);
ConvertToGF2VectorRep(x); fi;
return HashKeyBag(x,101,data[1],data[2]); end; fi; elif n < 256then
qq:=n; # log
i:=0; while qq<=256do
qq:=qq*n;
i:=i+1;
od; # i is now the number of field elements per byte
bytelen := QuoInt(Length(v),i); if bytelen<=8then # short 8-bit
return x->NumberFFVector(x,n); else # long 8 bit
data:=[3*GAPInfo.BytesPerVariable,bytelen]; # must check type #return x->HashKeyBag(x,101,data[1],data[2]);
return function(x) if not Is8BitVectorRep(x) or
Q_VEC8BIT(x)<>n then
Info(InfoWarning,1,"un- or miscompressed vector");
x:=ShallowCopy(x);
ConvertToVectorRep(x,n); fi;
return HashKeyBag(x,101,data[1],data[2]); end;
fi; elif n > 100000 and Characteristic( f ) < n then # large field, view it as an extension of its prime field # in order to avoid writing down all of its elements if Size( LeftActingDomain( f ) ) <> Characteristic( f ) then
f:= AsField( PrimeField( f ), f ); fi;
b:= Basis( f );
nn:= Size( LeftActingDomain( f ) );
return function( v )
local sy, x;
sy:= 0; for x in v do
sy:= n * sy + NumberFFVector( Coefficients( b, x ), nn );
od;
return sy; end; else # large field -- vector represented as plist.
f:=AsSSortedList(f);
return function(v)
local x,sy,p;
sy := 0; if IsZmodnZVectorRep(v) then for x in v![ELSPOS] do
sy := n*sy + (x-1);
od; else for x in v do
p := Position(f, x); # want to be quick: Assume no failures # if p = fail then # Error("NumberFFVector: Vector not over specified field"); # fi;
sy := n*sy + (p-1);
od; fi;
return sy; end; fi; end);
############################################################################# ## #M SparseIntKey(<objcol>) ##
InstallMethod(SparseIntKey,"for bounded tuples",true,
[ IsList,IsList and IsCyclotomicCollection ], 0, function(m, v) if Length(m)<> 3 or m[1]<>"BoundedTuples"then
TryNextMethod(); fi; # Due to the way BoundedTuples are presently implemented we expect the input # to the hash function to always be a list of positive immediate integers. This means # that using HashKeyWholeBag should be safe.
return function(x)
Assert(1, IsPositionsList(x)); if not IsPlistRep(x) then
x := AsPlist(x); fi;
return HashKeyBag(x, 1, 0, Length(x) * GAPInfo.BytesPerVariable); end;
# alternative code w/o HashKeyBag ## build a weight vector to distinguish lists. Make entries large while staying clearly within ## immediate int (2^55 replacing 2^60, since we take subsequent primes). #step:=NextPrimeInt(QuoInt(2^55,Maximum(m[2])*m[3])); #weights:=[1]; #len:=Length(v); ## up to 56 full, then increasingly reduce #len:=Minimum(len,8*RootInt(len)); #while Length(weights)<len do # Add(weights,Last(weights)+step); # step:=NextPrimeInt(step); #od; #return function(a) # return a*weights; #end;
end);
BindGlobal( "SparseIntKeyVecListAndMatrix", function(d,m)
local f,n,pow,fct; if IsList(d) and Length(d)>0 and IsMatrix(d[1]) then
f:=DefaultScalarDomainOfMatrixList(d); else
f:=DefaultScalarDomainOfMatrixList([m]); fi;
fct:=SparseIntKey(f^Length(m[1]),m[1]);
n:=Minimum(Size(f),11)^Minimum(12,QuoInt(Length(m[1]),2)); #pow:=n^Length(m[1]);
pow:=NextPrimeInt(n); # otherwise we produce huge numbers which take time
return function(x)
local i,gsy;
gsy:=0; for i in x do
gsy:=pow*gsy+fct(i);
od;
return gsy; end; end );
InstallMethod(SparseIntKey,"for lists of vectors",true,
[ IsFFECollColl,IsObject ], 0, function(m,v)
local f; if not (IsList(m) and IS_PLIST_REP(m) and ForAll(m,IsRowVector)) then
TryNextMethod(); fi;
f:=DefaultFieldOfMatrix(m);
return SparseIntKey(f^Length(v),v); end);
InstallMethod(SparseIntKey, "for matrices over finite field vector spaces",true,
[IsObject,IsFFECollColl and IsMatrix],0,
SparseIntKeyVecListAndMatrix);
InstallMethod(SparseIntKey, "for vector listsover finite field vector spaces",true,
[IsObject,IsFFECollColl and IsList],0,
SparseIntKeyVecListAndMatrix);
############################################################################# ## #M SparseIntKey( <dom>, <key> ) for row spaces over finite fields ##
InstallMethod( SparseIntKey, "for row spaces over finite fields", true,
[ IsObject,IsVectorSpace and IsRowSpace], 0, function( key, dom )
return function(key)
local sz, n, ret, k,d;
d:=LeftActingDomain( key );
sz := Size(d);
key := BasisVectors( CanonicalBasis( key ) );
n := sz ^ Length( key[1] );
ret := 1; for k in key do
ret := ret * n + NumberFFVector( k, sz );
od;
return ret; end; end );
InstallMethod(DenseIntKey,"integers",true,
[IsObject,IsPosInt],0, function(d,i) #T this function might cause problems if there are nonpositive integers #T used densely.
return IdFunc; end);
InstallMethod(SparseIntKey,"permutations, arbitrary domain",true,
[IsObject,IsInternalRep and IsPerm],0, function(d,pe)
return function(p)
local l;
l:=LARGEST_MOVED_POINT_PERM(p); if IsPerm4Rep(p) then # is it a proper 4byte perm? if l>65536then
return HashKeyBag(p,255,GAPInfo.BytesPerVariable,4*l); else # the permutation does not require 4 bytes. Trim in two # byte representation (we need to do this to get consistent # hash keys, regardless of representation.)
TRIM_PERM(p,l); fi; fi; # now we have a Perm2Rep:
return HashKeyBag(p,255,GAPInfo.BytesPerVariable,2*l); end; end);
#T Still to do: Permutation values based on base images: Method if the #T domain given is a permgroup.
InstallMethod(SparseIntKey,"kernel pc group elements",true,
[IsObject,
IsElementFinitePolycyclicGroup and IsDataObjectRep and IsNBitsPcWordRep],0, function(d,e)
local l,p; # we want to use an small shift to avoid cancellation due to similar bit # patterns in many bytes (the exponent values in most cases are very # small). The pcgs length is a reasonable small value-- otherwise we get # already overlap for the generators alone.
p:=FamilyObj(e)!.DefiningPcgs;
l:=NextPrimeInt(Length(p)+1);
p:=Product(RelativeOrders(p)); while Gcd(l,p)>1do
l:=NextPrimeInt(l);
od;
return e->HashKeyBag(e,l,DOUBLE_OBJLEN,-1); end);
InstallMethod(SparseIntKey,"pcgs element lists: i.e. pcgs",true,
[IsObject,IsElementFinitePolycyclicGroupCollection and IsList],0, function(d,p)
local o,e;
if IsPcgs(p) then
o:=OneOfPcgs(p); else
o:=One(p[1]); fi;
e:=SparseIntKey(false,o); # element hash fun
o:=DefiningPcgs(FamilyObj(o));
o:=Product(RelativeOrders(o)); # order of group
return function(x)
local i,h;
h:=0; for i in x do
h:=h*o+e(i);
od;
return h; end; end);
InstallMethod(SparseIntKey, "for an object and transformation",
[IsObject, IsTransformation], function(d, t)
return x-> NumberTransformation(t, DegreeOfTransformation(t)); end);
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-10-13)
¤
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.