Update .gitignore, _ChainedHashMap.pbi, HashMap.pbi, and 4 more files

This commit is contained in:
2026-09-30 22:18:19 +02:00
parent 605c4d1739
commit 90cd4d69b5
7 changed files with 353 additions and 105 deletions
+17 -2
View File
@@ -1,8 +1,23 @@
#YASS13_HashMap_Type = "Chained"
; Common prototypes every hashmap implementation must match.
Prototype.i HashMapProto_Create(SizePower.b)
Prototype.i HashMapProto_GetByHash(*Map, Hash.q)
Prototype.b HashMapProto_OverwriteByHash(*Map, *Data, Hash.q, *FreeingCallback = #Null)
Prototype HashMapProto_DeleteByHash(*Map, Hash.q)
Prototype HashMapProto_Free(*Map)
Prototype HashMapProto_FreeCallback(*Data)
CompilerIf #YASS13_HashMap_Type = "Chained"
XIncludeFile "./_ChainedHashMap.pbi"
Global HashMap_Create.HashMapProto_Create = ChainedHashMap::@Create()
Global HashMap_GetByHash.HashMapProto_GetByHash = ChainedHashMap::@GetByHash()
Global HashMap_OverwriteByHash.HashMapProto_OverwriteByHash = ChainedHashMap::@OverwriteByHash()
Global HashMap_DeleteByHash.HashMapProto_DeleteByHash = ChainedHashMap::@DeleteByHash()
Global HashMap_Free.HashMapProto_Free = ChainedHashMap::@Free()
Global HashMap_NoopFree.HashMapProto_FreeCallback = ChainedHashMap::@NoopFree()
CompilerElse
CompilerError("You must defined a valid core hashmap type !")
CompilerError("You must defined a valid core hashmap type !")
CompilerEndIf
+113 -103
View File
@@ -1,121 +1,131 @@
EnableExplicit
DeclareModule ChainedHashMap
EnableExplicit
#HashMap_InitialPower = 9
#HashMap_InsertIterations = 100000
#InitialPower = 9
#InsertIterations = 100000
;{
Structure Bucket
*BucketData
*Next.Bucket
Hash.q
EndStructure
Structure ChainedHashMapBucket
*BucketData
*Next.ChainedHashMapBucket
Hash.q
EndStructure
Structure HashMap
EntryCount.i
Capacity.i
SizePower.a
*Buckets.Bucket[0]
EndStructure
Structure ChainedHashMap
EntryCount.i
Capacity.i
SizePower.a
*Buckets.ChainedHashMapBucket[0]
EndStructure
Prototype CbFree(*Data)
Declare.i Create(SizePower.b)
Declare.i GetByHash(*CHM.HashMap, Hash.q)
Declare.b OverwriteByHash(*CHM.HashMap, *Data, Hash.q, *FreeingCallback.CbFree = #Null)
Declare DeleteByHash(*CHM.HashMap, Hash.q)
Declare Free(*CHM.HashMap)
Declare NoopFree(*Data)
EndDeclareModule
Prototype CbFree(*Data)
Module ChainedHashMap
EnableExplicit
Procedure.l MakeBitMask(BitCount.b)
EnableASM
MOV eax, $00000001
MOV cl, BitCount
SHL eax, cl
DEC eax
ProcedureReturn
DisableASM
EndProcedure
Procedure.l MakeBitMask(BitCount.b)
EnableASM
MOV eax, $00000001
MOV cl, BitCount
SHL eax, cl
DEC eax
ProcedureReturn
DisableASM
EndProcedure
Procedure.i CHM_Create(SizePower.b)
Protected *CHM.ChainedHashMap = AllocateMemory(SizeOf(ChainedHashMap) + (SizeOf(Integer) * (MakeBitMask(SizePower) + 1)))
If *CHM <> #Null
*CHM\EntryCount = 0
*CHM\SizePower = SizePower
Protected iBucket
For iBucket = 0 To MakeBitMask(SizePower)
*CHM\Buckets[iBucket] = #Null
Next
EndIf
ProcedureReturn *CHM
EndProcedure
Procedure.i Create(SizePower.b)
Protected *CHM.HashMap = AllocateMemory(SizeOf(HashMap) + (SizeOf(Integer) * (MakeBitMask(SizePower) + 1)))
Procedure.i CHM_GetByHash(*CHM.ChainedHashMap, Hash.q)
If *CHM <> #Null
Protected *CurrentBucket.ChainedHashMapBucket = *CHM\Buckets[(Hash & MakeBitMask(*CHM\SizePower))]
While *CurrentBucket <> #Null
If *CurrentBucket\Hash = Hash
ProcedureReturn *CurrentBucket\BucketData
EndIf
*CurrentBucket = *CurrentBucket\Next
Wend
EndIf
ProcedureReturn #Null
EndProcedure
If *CHM <> #Null
*CHM\EntryCount = 0
*CHM\SizePower = SizePower
Procedure.b CHM_OverwriteByHash(*CHM.ChainedHashMap, *Data, Hash.q, *FreeingCallback.CbFree = #Null)
If *CHM <> #Null
Protected *PreviousBucket.ChainedHashMapBucket = #Null
Protected *CurrentBucket.ChainedHashMapBucket = *CHM\Buckets[(Hash & MakeBitMask(*CHM\SizePower))]
; We iterate over the bucket chain until we find a collision or an in-between.
While *CurrentBucket <> #Null
If *CurrentBucket\Hash >= Hash
Break
EndIf
*PreviousBucket = *CurrentBucket
*CurrentBucket = *CurrentBucket\Next
Wend
If *CurrentBucket = #Null Or *CurrentBucket\Hash <> Hash
; We either reached the end of the list, or no buckets was in the current slot.
; Or, we have an in-between, or we are at the start of the list.
Protected *NewBucket.ChainedHashMapBucket = AllocateMemory(SizeOf(ChainedHashMapBucket))
If *NewBucket <> #Null
*NewBucket\Next = *CurrentBucket
*NewBucket\BucketData = *Data
*NewBucket\Hash = Hash
If *PreviousBucket <> #Null
; In-between, or we are at the start of the List.
*PreviousBucket\Next = *NewBucket
Else
; Start of the list.
*CHM\Buckets[(Hash & MakeBitMask(*CHM\SizePower))] = *NewBucket
Protected iBucket
For iBucket = 0 To MakeBitMask(SizePower)
*CHM\Buckets[iBucket] = #Null
Next
EndIf
ProcedureReturn *CHM
EndProcedure
Procedure.i GetByHash(*CHM.HashMap, Hash.q)
If *CHM <> #Null
Protected *CurrentBucket.Bucket = *CHM\Buckets[(Hash & MakeBitMask(*CHM\SizePower))]
While *CurrentBucket <> #Null
If *CurrentBucket\Hash = Hash
ProcedureReturn *CurrentBucket\BucketData
EndIf
*CHM\EntryCount = *CHM\EntryCount + 1
*CurrentBucket = *CurrentBucket\Next
Wend
EndIf
ProcedureReturn #Null
EndProcedure
Procedure.b OverwriteByHash(*CHM.HashMap, *Data, Hash.q, *FreeingCallback.CbFree = #Null)
If *CHM <> #Null
Protected *PreviousBucket.Bucket = #Null
Protected *CurrentBucket.Bucket = *CHM\Buckets[(Hash & MakeBitMask(*CHM\SizePower))]
; We iterate over the bucket chain until we find a collision or an in-between.
While *CurrentBucket <> #Null
If *CurrentBucket\Hash >= Hash
Break
EndIf
*PreviousBucket = *CurrentBucket
*CurrentBucket = *CurrentBucket\Next
Wend
If *CurrentBucket = #Null Or *CurrentBucket\Hash <> Hash
; We either reached the end of the list, or no buckets was in the current slot.
; Or, we have an in-between, or we are at the start of the list.
Protected *NewBucket.Bucket = AllocateMemory(SizeOf(Bucket))
If *NewBucket <> #Null
*NewBucket\Next = *CurrentBucket
*NewBucket\BucketData = *Data
*NewBucket\Hash = Hash
If *PreviousBucket <> #Null
; In-between, or we are at the start of the List.
*PreviousBucket\Next = *NewBucket
Else
; Start of the list.
*CHM\Buckets[(Hash & MakeBitMask(*CHM\SizePower))] = *NewBucket
EndIf
*CHM\EntryCount = *CHM\EntryCount + 1
ProcedureReturn #True
EndIf
ElseIf *FreeingCallback <> #Null
; Handling collision.
CallFunctionFast(*FreeingCallback, *CurrentBucket\BucketData)
*CurrentBucket\BucketData = *Data
ProcedureReturn #True
EndIf
ElseIf *FreeingCallback <> #Null
; Handling collision.
CallFunctionFast(*FreeingCallback, *CurrentBucket\BucketData)
*CurrentBucket\BucketData = *Data
ProcedureReturn #True
; Implied else: Handling collision while forbidden to overwrite => doing nothing.
EndIf
; Implied else: Handling collision while forbidden to overwrite => doing nothing.
EndIf
ProcedureReturn #False
EndProcedure
Procedure CHM_DeleteByHash(*CHM.ChainedHashMap, Hash.q)
EndProcedure
ProcedureReturn #False
EndProcedure
Procedure CHM_Free(*CHM.ChainedHashMap)
EndProcedure
Procedure DeleteByHash(*CHM.HashMap, Hash.q)
Procedure NoopFree(*Data) : EndProcedure
EndProcedure
Procedure Free(*CHM.HashMap)
EndProcedure
Procedure NoopFree(*Data) : EndProcedure
EndModule