Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
This file describes changes in the orb package.

5.0.0 (TODO)
- Remove legacy APIs `InitHT`, `NewHT`, `AddHT`, `ValueHT`, `GrowHT`.
Instead use `HTCreate`, `HTAdd`, `HTValue`, `HTDelete` and `HTUpdate`.

4.9.2 (2025-01-03)
- Fix compilation with GCC 15
- Prepare for a future GAP version introducing PreImagesElmNC
Expand Down
2 changes: 1 addition & 1 deletion PackageInfo.g
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ SetPackageInfo( rec(

PackageName := "orb",
Subtitle := "Methods to enumerate orbits",
Version := "4.9.2",
Version := "5.0.0dev",
Date := "03/01/2025", # dd/mm/yyyy format
License := "GPL-3.0-or-later",

Expand Down
2 changes: 1 addition & 1 deletion doc/basic.xml
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ list:
Note that if you use this feature, the hash table cannot grow
automatically any more, unless you also use the components
<C>hfbig</C> and <C>hfdbig</C> as well. See the description
of <Ref Func="GrowHT"/> for an explanation how to use this
of <Ref Func="HTGrow"/> for an explanation how to use this
feature.
</Item>
<Mark><C>genstoapply</C></Mark>
Expand Down
113 changes: 0 additions & 113 deletions doc/hash.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,6 @@ The basic functions to work with hash tables are <Ref
Oper="HTCreate"/>, <Ref Oper="HTAdd"/>, <Ref Oper="HTValue"/>,
<Ref Oper="HTDelete"/> and <Ref Oper="HTUpdate"/>. They are described
in Section <Ref Sect="hashtables"/>.

<P/>
The legacy functions from older versions of this package
to work with hash tables are <Ref Func="NewHT"/>,
<Ref Func="AddHT"/>, and <Ref Func="ValueHT"/>. They are described
in Section <Ref Sect="oldhashtables"/>. In the next section, we first
describe the infrastructure for hash functions.
</Section>

<Section Label="hashfunc">
Expand Down Expand Up @@ -397,112 +390,6 @@ hash values.

</Section>

<Section Label="oldhashtables">
<Heading>Using hash tables (legacy code)</Heading>

Note that the functions described in this section are obsolete since
version 3.0 of <Package>orb</Package> and are only kept for backward
compatibility. Please use the functions in Section <Ref
Sect="hashtables"/> in new code.

<P/>
The following functions are needed to use hash tables. For details
about the data structures see Section <Ref Sect="hashdata"/>.

<ManSection>
<Func Name="NewHT" Arg="sample, len"/>
<Returns> a new hash table object </Returns>
<Description>
A new hash table for objects like <A>sample</A> of length <A>len</A>
is created. Note that it is a good idea to choose a prime number as
the hash length due to the algorithm for collision handling which
works particularly well in that case. The hash function is chosen
automatically. The resulting object can be used with the functions
<Ref Func="AddHT"/> and <Ref Func="ValueHT"/>. It will start with length
<A>len</A> but will grow as necessary.
</Description>
</ManSection>

<ManSection>
<Func Name="AddHT" Arg="ht, ob, val"/>
<Returns> an integer or fail </Returns>
<Description>
Stores the object <A>ob</A> into the hash table <A>ht</A> and stores
the value <A>val</A> together with <A>ob</A>. The result is
<K>fail</K> if an error occurred, which can only be that the hash
table is already full. This can only happen, if the hash table cannot
grow automatically.
<P/>
If no error occurs, the result is an integer indicating the place in the
hash table where the object is stored. Note that once the hash table
grows automatically this number is no longer the same!
<P/>
If the value <A>val</A> is <K>true</K> for all objects in the hash,
no extra memory is used for the values. All other values are stored
in the hash. The value <K>fail</K> cannot be stored as it indicates
that the object is not found in the hash.
<P/>
See Section <Ref Sect="hashdata"/> for details on the data structures and
especially about memory requirements.
</Description>
</ManSection>

<ManSection>
<Func Name="ValueHT" Arg="ht, ob"/>
<Returns> the stored value, <K>true</K>, or <K>fail</K> </Returns>
<Description>
Looks up the object <A>ob</A> in the hash table <A>ht</A>. If the object
is not found, <K>fail</K> is returned. Otherwise, the value stored with
the object is returned. Note that if this value was <K>true</K>
no extra memory is used for this.
</Description>
</ManSection>

The following function is only documented for the sake of completeness
and for emergency situations, where <Ref Func="NewHT"/> tries to be
too intelligent.

<ManSection>
<Func Name="InitHT" Arg="len, hfun, eqfun"/>
<Returns> a new hash table object </Returns>
<Description>
This is usually only an internal function. It is called from
<Ref Func="NewHT"/>. The argument <A>len</A> is the length of the
hash table, <A>hfun</A> is the hash function record as returned
by <Ref Oper="ChooseHashFunction"/> and <A>eqfun</A> is a comparison
function taking two arguments and returning <K>true</K> or <K>false</K>.
<P/>
Note that automatic growing is switched on for the new hash table which
means that if the hash table grows, a new hash function is chosen using
<Ref Oper="ChooseHashFunction"/>. If you do not want this, change the
component <C>cangrow</C> to <K>false</K> after creating the hash table.
</Description>
</ManSection>

<ManSection>
<Func Name="GrowHT" Arg="ht, ob"/>
<Returns> nothing </Returns>
<Description>
This is a more or less internal function. It is called when the space
in a hash table becomes scarce. The first argument <A>ht</A> must be a
hash table object, the second a sample point.
The function increases the hash size
by a factor of 2 for hash tables and 20 for tree hash tables.
This makes it necessary to choose a new hash
function. Usually this is done with the usual
<C>ChooseHashFunction</C> method. However, one can assign the two
components <C>hfbig</C> and <C>hfdbig</C> to a function and a record
respectively. In that case, upon growing the hash, a new hash function
is created by taking the function <C>hfbig</C> together with
<C>hfdbig</C> as second data argument and reducing the resulting
integer modulo the hash length. In this way one can specify a hash
function suitable for all hash sizes by simply producing big enough
hash values.
</Description>
</ManSection>

</Section>

<Section Label="hashdata">
<Heading> The data structures for hash tables </Heading>

Expand Down
6 changes: 0 additions & 6 deletions gap/hash.gd
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@
# Generic hashing code:
########################

DeclareGlobalFunction( "InitHT" );
DeclareGlobalFunction( "NewHT" );
DeclareGlobalFunction( "AddHT" );
DeclareGlobalFunction( "ValueHT" );
DeclareGlobalFunction( "GrowHT" );

BindGlobal( "HashTabFamily", NewFamily("HashTabFamily") );
DeclareCategory( "IsHashTab", IsComponentObjectRep);
DeclareRepresentation( "IsHashTabRep", IsHashTab, [] );
Expand Down
133 changes: 0 additions & 133 deletions gap/hash.gi
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,6 @@
##
#############################################################################

InstallGlobalFunction( InitHT, function(len, hfun, eqfun)
return rec(els := [], # the elements to hash
vals := [], # a value for each element, "true" not stored
len := len, # the length of the hash
nr := 0, # number of elements in hash
hf := hfun.func, # the hash function
hfd := hfun.data, # data for the second argument to hf
eqf := eqfun, # a comparison function
collisions := 0, # number of collisions
accesses := 0, # number of accesses
cangrow := false, # flag, whether hash table may grow
ishash := true, # a "magic" entry
);
end );

InstallGlobalFunction( NewHT, function(sample,len)
local eqfun,hfun,ht;
hfun := ChooseHashFunction(sample,len);
if hfun = fail then
return fail;
fi;
eqfun := ApplicableMethod(\=,[sample,sample]);
if eqfun = fail then eqfun := EQ; fi;
if len < 11 then len := 11; fi; # to avoid complete fillup!
ht := InitHT(len,hfun,eqfun);
ht.cangrow := true;
return ht;
end );

InstallMethod(ViewObj, "for hash tables", [IsRecord],
function(ht)
if IsBound(ht.ishash) and
Expand All @@ -63,110 +34,6 @@ InstallMethod(ViewObj, "for hash tables", [IsRecord],
fi;
end);

InstallGlobalFunction( AddHT, function(ht, x, val)
local h,g;
ht.accesses := ht.accesses + 1;
if ht.nr * 10 > ht.len * 8 then
if IsBound(ht.cangrow) then
Info(InfoOrb,3,"Hash table too full, growing...");
GrowHT(ht,x);
else
Info(InfoOrb,1,"Hash table too full, cannot grow...");
return fail;
fi;
fi;
h := ht.hf(x,ht.hfd);
if IsBound(ht.els[h]) then
g := GcdInt(ht.len,h);
if g = 1 then g := h; else g := 1; fi;
repeat
ht.collisions := ht.collisions + 1;
h := h+g;
if h>ht.len then h := h - ht.len; fi;
if not(IsBound(ht.alert)) and QuoInt(ht.collisions,ht.accesses) > 100 then
# We have a problem!
Info(InfoOrb,1,"Alarm: Collision warning: Collisions: ",
ht.collisions," Accesses: ",ht.accesses,"!");
if not(IsBound(ht.cangrow)) then
ht.alert := true;
else
GrowHT(ht,x);
return AddHT(ht,x,val);
fi;
fi;
until not(IsBound(ht.els[h]));
fi;
ht.els[h] := x;
if val <> true then ht.vals[h] := val; fi;
ht.nr := ht.nr+1;
return h;
end );

InstallGlobalFunction( ValueHT, function(ht, x)
local h,g;
ht.accesses := ht.accesses + 1;
h := ht.hf(x,ht.hfd);
g := 0;
while IsBound(ht.els[h]) do
if ht.eqf(ht.els[h],x) then
if IsBound(ht.vals[h]) then
return ht.vals[h];
else
return true;
fi;
fi;
if g = 0 then
g := GcdInt(ht.len,h);
if g = 1 then g := h; else g := 1; fi;
fi;
ht.collisions := ht.collisions + 1;
h := h+g;
if h>ht.len then h := h - ht.len; fi;
od;
return fail;
end );

InstallGlobalFunction( GrowHT, function(ht,x)
local i,oldels,oldlen,oldvals;

oldels := ht.els;
oldvals := ht.vals;
oldlen := ht.len;

ht.els := [];
ht.vals := [];
ht.len := NextPrimeInt(ht.len * 2+1);
Info(InfoOrb,2,"Growing hash table to length ",ht.len," !!!");
if IsBound(ht.hfbig) and IsBound(ht.htdbig) then
ht.hf := ORB_HashFunctionModWrapper;
ht.hfd := [ht.hfbig,ht.hfdbig,ht.len];
else
ht.hf := ChooseHashFunction(x,ht.len);
if ht.hf = fail then
Error("Could not find hash function for sample object");
return fail;
fi;
ht.hfd := ht.hf.data;
ht.hf := ht.hf.func;
fi;
ht.nr := 0;
ht.collisions := 0;
ht.accesses := 0;
# Now copy into new hash:
for i in [1..oldlen] do
if IsBound(oldels[i]) then
if IsBound(oldvals[i]) then
AddHT(ht,oldels[i],oldvals[i]);
else
AddHT(ht,oldels[i],true);
fi;
fi;
od;
Info(InfoOrb,3,"Done.");
end );

# The new interface for hashes:

InstallMethod( HTCreate, "for an object",
[ IsObject ],
function( x )
Expand Down
8 changes: 0 additions & 8 deletions tst/orbitspeedtest.g
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,6 @@ for i in [1..Length(l)] do
od;
Print("Time: ",Runtime()-ti,"\n");

#t := NewHT(o[1],200000);
#a:=1;b:=2;c:=3; GASMAN("collect");
#ti := Runtime();
#for i in [1..Length(l)] do
# AddHT(t,l[i],i);
#od;
#Print("Time: ",Runtime()-ti,"\n");

ti := Runtime();
for i in [1..Length(l)] do
if HTValue(t,l[i]) <> i then Error(); fi;
Expand Down
Loading