diff --git a/CHANGES b/CHANGES index d628373..e8c4b6e 100644 --- a/CHANGES +++ b/CHANGES @@ -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 diff --git a/PackageInfo.g b/PackageInfo.g index 65f3fda..569a8c3 100644 --- a/PackageInfo.g +++ b/PackageInfo.g @@ -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", diff --git a/doc/basic.xml b/doc/basic.xml index 193363e..b468fd4 100644 --- a/doc/basic.xml +++ b/doc/basic.xml @@ -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 hfbig and hfdbig as well. See the description - of for an explanation how to use this + of for an explanation how to use this feature. genstoapply diff --git a/doc/hash.xml b/doc/hash.xml index f6b2be4..c239b37 100644 --- a/doc/hash.xml +++ b/doc/hash.xml @@ -46,13 +46,6 @@ The basic functions to work with hash tables are , , , and . They are described in Section . - -

-The legacy functions from older versions of this package -to work with hash tables are , -, and . They are described -in Section . In the next section, we first -describe the infrastructure for hash functions.

@@ -397,112 +390,6 @@ hash values.
-
-Using hash tables (legacy code) - -Note that the functions described in this section are obsolete since -version 3.0 of orb and are only kept for backward -compatibility. Please use the functions in Section in new code. - -

-The following functions are needed to use hash tables. For details -about the data structures see Section . - - - - a new hash table object - -A new hash table for objects like sample of length len -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 - and . It will start with length -len but will grow as necessary. - - - - - - an integer or fail - -Stores the object ob into the hash table ht and stores -the value val together with ob. The result is -fail 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. -

-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! -

-If the value val is true for all objects in the hash, -no extra memory is used for the values. All other values are stored -in the hash. The value fail cannot be stored as it indicates -that the object is not found in the hash. -

-See Section for details on the data structures and -especially about memory requirements. - - - - - - the stored value, true, or fail - -Looks up the object ob in the hash table ht. If the object -is not found, fail is returned. Otherwise, the value stored with -the object is returned. Note that if this value was true -no extra memory is used for this. - - - -The following function is only documented for the sake of completeness -and for emergency situations, where tries to be -too intelligent. - - - - a new hash table object - -This is usually only an internal function. It is called from -. The argument len is the length of the -hash table, hfun is the hash function record as returned -by and eqfun is a comparison -function taking two arguments and returning true or false. -

-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 -. If you do not want this, change the -component cangrow to false after creating the hash table. - - - - - - nothing - -This is a more or less internal function. It is called when the space -in a hash table becomes scarce. The first argument ht 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 -ChooseHashFunction method. However, one can assign the two -components hfbig and hfdbig to a function and a record -respectively. In that case, upon growing the hash, a new hash function -is created by taking the function hfbig together with -hfdbig 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. - - - -

-
The data structures for hash tables diff --git a/gap/hash.gd b/gap/hash.gd index 5ca9672..aa8f68c 100644 --- a/gap/hash.gd +++ b/gap/hash.gd @@ -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, [] ); diff --git a/gap/hash.gi b/gap/hash.gi index 9f7cb5c..3a6b474 100644 --- a/gap/hash.gi +++ b/gap/hash.gi @@ -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 @@ -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 ) diff --git a/tst/orbitspeedtest.g b/tst/orbitspeedtest.g index 8562478..c4db94f 100644 --- a/tst/orbitspeedtest.g +++ b/tst/orbitspeedtest.g @@ -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;