lib/pure/a-c - Dropped 'T' from types
This commit is contained in:
parent
1c426c613c
commit
192ba3bbc0
13 changed files with 477 additions and 470 deletions
|
|
@ -46,24 +46,25 @@ const
|
|||
|
||||
when sizeof(int) == 4: # 32bit
|
||||
type
|
||||
TRaw = range[0..1073741823]
|
||||
Raw = range[0..1073741823]
|
||||
## The range of uint values that can be stored directly in a value slot
|
||||
## when on a 32 bit platform
|
||||
|
||||
{.deprecated: [TRaw: Raw].}
|
||||
elif sizeof(int) == 8: # 64bit
|
||||
type
|
||||
TRaw = range[0..4611686018427387903]
|
||||
Raw = range[0..4611686018427387903]
|
||||
## The range of uint values that can be stored directly in a value slot
|
||||
## when on a 64 bit platform
|
||||
{.deprecated: [TRaw: Raw].}
|
||||
else:
|
||||
{.error: "unsupported platform".}
|
||||
|
||||
type
|
||||
TEntry = tuple
|
||||
Entry = tuple
|
||||
key: int
|
||||
value: int
|
||||
|
||||
TEntryArr = ptr array[0..10_000_000, TEntry]
|
||||
EntryArr = ptr array[0..10_000_000, Entry]
|
||||
|
||||
PConcTable[K,V] = ptr object {.pure.}
|
||||
len: int
|
||||
|
|
@ -72,8 +73,8 @@ type
|
|||
copyIdx: int
|
||||
copyDone: int
|
||||
next: PConcTable[K,V]
|
||||
data: TEntryArr
|
||||
|
||||
data: EntryArr
|
||||
{.deprecated: [TEntry: Entry, TEntryArr: EntryArr.}
|
||||
|
||||
proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int,
|
||||
expVal: int, match: bool): int
|
||||
|
|
@ -84,7 +85,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int,
|
|||
proc newLFTable*[K,V](size: int = minTableSize): PConcTable[K,V] =
|
||||
let
|
||||
dataLen = max(nextPowerOfTwo(size), minTableSize)
|
||||
dataSize = dataLen*sizeof(TEntry)
|
||||
dataSize = dataLen*sizeof(Entry)
|
||||
dataMem = allocShared0(dataSize)
|
||||
tableSize = 7 * intSize
|
||||
tableMem = allocShared0(tableSize)
|
||||
|
|
@ -95,7 +96,7 @@ proc newLFTable*[K,V](size: int = minTableSize): PConcTable[K,V] =
|
|||
table.copyIdx = 0
|
||||
table.copyDone = 0
|
||||
table.next = nil
|
||||
table.data = cast[TEntryArr](dataMem)
|
||||
table.data = cast[EntryArr](dataMem)
|
||||
result = table
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
|
@ -107,7 +108,7 @@ proc deleteConcTable[K,V](tbl: PConcTable[K,V]) =
|
|||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
proc `[]`[K,V](table: var PConcTable[K,V], i: int): var TEntry {.inline.} =
|
||||
proc `[]`[K,V](table: var PConcTable[K,V], i: int): var Entry {.inline.} =
|
||||
table.data[i]
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
|
@ -191,7 +192,7 @@ proc resize[K,V](self: PConcTable[K,V]): PConcTable[K,V] =
|
|||
#proc keyEQ[K](key1: ptr K, key2: ptr K): bool {.inline.} =
|
||||
proc keyEQ[K](key1: int, key2: int): bool {.inline.} =
|
||||
result = false
|
||||
when K is TRaw:
|
||||
when K is Raw:
|
||||
if key1 == key2:
|
||||
result = true
|
||||
else:
|
||||
|
|
@ -236,7 +237,7 @@ proc copySlot[K,V](idx: int, oldTbl: var PConcTable[K,V], newTbl: var PConcTable
|
|||
break
|
||||
#echo("oldVal was = ", oldVal, " set it to prime ", box)
|
||||
if isPrime(oldVal) and isTomb(oldVal):
|
||||
#when not (K is TRaw):
|
||||
#when not (K is Raw):
|
||||
# deallocShared(popPtr[K](oldKey))
|
||||
return false
|
||||
if isTomb(oldVal):
|
||||
|
|
@ -343,7 +344,7 @@ proc helpCopy[K,V](table: var PConcTable[K,V]): PConcTable[K,V] =
|
|||
proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int,
|
||||
expVal: int, match: bool): int =
|
||||
#echo("-try set- in table ", " key = ", (popPtr[K](key)[]), " val = ", val)
|
||||
when K is TRaw:
|
||||
when K is Raw:
|
||||
var idx = hashInt(key)
|
||||
else:
|
||||
var idx = popPtr[K](key)[].hash
|
||||
|
|
@ -428,7 +429,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int,
|
|||
|
||||
proc getVal[K,V](table: var PConcTable[K,V], key: int): int =
|
||||
#echo("-try get- key = " & $key)
|
||||
when K is TRaw:
|
||||
when K is Raw:
|
||||
var idx = hashInt(key)
|
||||
else:
|
||||
var idx = popPtr[K](key)[].hash
|
||||
|
|
@ -468,37 +469,37 @@ proc getVal[K,V](table: var PConcTable[K,V], key: int): int =
|
|||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#proc set*(table: var PConcTable[TRaw,TRaw], key: TRaw, val: TRaw) =
|
||||
#proc set*(table: var PConcTable[Raw,Raw], key: Raw, val: Raw) =
|
||||
# discard setVal(table, pack(key), pack(key), 0, false)
|
||||
|
||||
#proc set*[V](table: var PConcTable[TRaw,V], key: TRaw, val: ptr V) =
|
||||
#proc set*[V](table: var PConcTable[Raw,V], key: Raw, val: ptr V) =
|
||||
# discard setVal(table, pack(key), cast[int](val), 0, false)
|
||||
|
||||
proc set*[K,V](table: var PConcTable[K,V], key: var K, val: var V) =
|
||||
when not (K is TRaw):
|
||||
when not (K is Raw):
|
||||
var newKey = cast[int](copyShared(key))
|
||||
else:
|
||||
var newKey = pack(key)
|
||||
when not (V is TRaw):
|
||||
when not (V is Raw):
|
||||
var newVal = cast[int](copyShared(val))
|
||||
else:
|
||||
var newVal = pack(val)
|
||||
var oldPtr = pop(setVal(table, newKey, newVal, 0, false))
|
||||
#echo("oldPtr = ", cast[int](oldPtr), " newPtr = ", cast[int](newPtr))
|
||||
when not (V is TRaw):
|
||||
when not (V is Raw):
|
||||
if newVal != oldPtr and oldPtr != 0:
|
||||
deallocShared(cast[ptr V](oldPtr))
|
||||
|
||||
|
||||
|
||||
proc get*[K,V](table: var PConcTable[K,V], key: var K): V =
|
||||
when not (V is TRaw):
|
||||
when not (K is TRaw):
|
||||
when not (V is Raw):
|
||||
when not (K is Raw):
|
||||
return popPtr[V](getVal(table, cast[int](key.addr)))[]
|
||||
else:
|
||||
return popPtr[V](getVal(table, pack(key)))[]
|
||||
else:
|
||||
when not (K is TRaw):
|
||||
when not (K is Raw):
|
||||
return popRaw(getVal(table, cast[int](key.addr)))
|
||||
else:
|
||||
return popRaw(getVal(table, pack(key)))
|
||||
|
|
@ -535,23 +536,24 @@ when not defined(testing) and isMainModule:
|
|||
|
||||
|
||||
type
|
||||
TTestObj = tuple
|
||||
TestObj = tuple
|
||||
thr: int
|
||||
f0: int
|
||||
f1: int
|
||||
|
||||
TData = tuple[k: string,v: TTestObj]
|
||||
PDataArr = array[0..numTests-1, TData]
|
||||
Dict = PConcTable[string,TTestObj]
|
||||
Data = tuple[k: string,v: TestObj]
|
||||
PDataArr = array[0..numTests-1, Data]
|
||||
Dict = PConcTable[string,TestObj]
|
||||
{.deprecated: [TTestObj: TestObj, TData: Data].}
|
||||
|
||||
var
|
||||
thr: array[0..numThreads-1, TThread[Dict]]
|
||||
thr: array[0..numThreads-1, Thread[Dict]]
|
||||
|
||||
table = newLFTable[string,TTestObj](8)
|
||||
table = newLFTable[string,TestObj](8)
|
||||
rand = newMersenneTwister(2525)
|
||||
|
||||
proc createSampleData(len: int): PDataArr =
|
||||
#result = cast[PDataArr](allocShared0(sizeof(TData)*numTests))
|
||||
#result = cast[PDataArr](allocShared0(sizeof(Data)*numTests))
|
||||
for i in 0..len-1:
|
||||
result[i].k = "mark" & $(i+1)
|
||||
#echo("mark" & $(i+1), " ", hash("mark" & $(i+1)))
|
||||
|
|
|
|||
|
|
@ -30,25 +30,25 @@ const
|
|||
IntMask = 1 shl IntShift - 1
|
||||
|
||||
type
|
||||
PTrunk = ref TTrunk
|
||||
TTrunk {.final.} = object
|
||||
PTrunk = ref Trunk
|
||||
Trunk {.final.} = object
|
||||
next: PTrunk # all nodes are connected with this pointer
|
||||
key: int # start address at bit 0
|
||||
bits: array[0..IntsPerTrunk - 1, BitScalar] # a bit vector
|
||||
|
||||
TTrunkSeq = seq[PTrunk]
|
||||
TrunkSeq = seq[PTrunk]
|
||||
IntSet* = object ## an efficient set of 'int' implemented as a sparse bit set
|
||||
counter, max: int
|
||||
head: PTrunk
|
||||
data: TTrunkSeq
|
||||
data: TrunkSeq
|
||||
|
||||
{.deprecated: [TIntSet: IntSet].}
|
||||
{.deprecated: [TIntSet: IntSet, TTrunk: Trunk, TTrunkSeq: TrunkSeq].}
|
||||
|
||||
proc mustRehash(length, counter: int): bool {.inline.} =
|
||||
assert(length > counter)
|
||||
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||
|
||||
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
||||
proc nextTry(h, maxHash: Hash): Hash {.inline.} =
|
||||
result = ((5 * h) + 1) and maxHash
|
||||
|
||||
proc intSetGet(t: IntSet, key: int): PTrunk =
|
||||
|
|
@ -59,7 +59,7 @@ proc intSetGet(t: IntSet, key: int): PTrunk =
|
|||
h = nextTry(h, t.max)
|
||||
result = nil
|
||||
|
||||
proc intSetRawInsert(t: IntSet, data: var TTrunkSeq, desc: PTrunk) =
|
||||
proc intSetRawInsert(t: IntSet, data: var TrunkSeq, desc: PTrunk) =
|
||||
var h = desc.key and t.max
|
||||
while data[h] != nil:
|
||||
assert(data[h] != desc)
|
||||
|
|
@ -68,7 +68,7 @@ proc intSetRawInsert(t: IntSet, data: var TTrunkSeq, desc: PTrunk) =
|
|||
data[h] = desc
|
||||
|
||||
proc intSetEnlarge(t: var IntSet) =
|
||||
var n: TTrunkSeq
|
||||
var n: TrunkSeq
|
||||
var oldMax = t.max
|
||||
t.max = ((t.max + 1) * 2) - 1
|
||||
newSeq(n, t.max + 1)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ when not defined(nimhygiene):
|
|||
# codes should never be needed, and this can pack more entries per cache-line.
|
||||
# Losing hcode entirely is also possible - if some element value is forbidden.
|
||||
type
|
||||
KeyValuePair[A] = tuple[hcode: THash, key: A]
|
||||
KeyValuePair[A] = tuple[hcode: Hash, key: A]
|
||||
KeyValuePairSeq[A] = seq[KeyValuePair[A]]
|
||||
HashSet* {.myShallow.}[A] = object ## \
|
||||
## A generic hash set.
|
||||
|
|
@ -43,10 +43,10 @@ type
|
|||
|
||||
# hcode for real keys cannot be zero. hcode==0 signifies an empty slot. These
|
||||
# two procs retain clarity of that encoding without the space cost of an enum.
|
||||
proc isEmpty(hcode: THash): bool {.inline.} =
|
||||
proc isEmpty(hcode: Hash): bool {.inline.} =
|
||||
result = hcode == 0
|
||||
|
||||
proc isFilled(hcode: THash): bool {.inline.} =
|
||||
proc isFilled(hcode: Hash): bool {.inline.} =
|
||||
result = hcode != 0
|
||||
|
||||
proc isValid*[A](s: HashSet[A]): bool =
|
||||
|
|
@ -58,7 +58,7 @@ proc isValid*[A](s: HashSet[A]): bool =
|
|||
## initialized. Example:
|
||||
##
|
||||
## .. code-block ::
|
||||
## proc savePreferences(options: TSet[string]) =
|
||||
## proc savePreferences(options: Set[string]) =
|
||||
## assert options.isValid, "Pass an initialized set!"
|
||||
## # Do stuff here, may crash in release builds!
|
||||
result = not s.data.isNil
|
||||
|
|
@ -72,7 +72,7 @@ proc len*[A](s: HashSet[A]): int =
|
|||
##
|
||||
## .. code-block::
|
||||
##
|
||||
## var values: TSet[int]
|
||||
## var values: Set[int]
|
||||
## assert(not values.isValid)
|
||||
## assert values.len == 0
|
||||
result = s.counter
|
||||
|
|
@ -123,15 +123,15 @@ proc rightSize*(count: Natural): int {.inline.} =
|
|||
## Internally, we want mustRehash(rightSize(x), x) == false.
|
||||
result = nextPowerOfTwo(count * 3 div 2 + 4)
|
||||
|
||||
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
||||
proc nextTry(h, maxHash: Hash): Hash {.inline.} =
|
||||
result = (h + 1) and maxHash
|
||||
|
||||
template rawGetKnownHCImpl() {.dirty.} =
|
||||
var h: THash = hc and high(s.data) # start with real hash value
|
||||
var h: Hash = hc and high(s.data) # start with real hash value
|
||||
while isFilled(s.data[h].hcode):
|
||||
# Compare hc THEN key with boolean short circuit. This makes the common case
|
||||
# zero ==key's for missing (e.g.inserts) and exactly one ==key for present.
|
||||
# It does slow down succeeding lookups by one extra THash cmp&and..usually
|
||||
# It does slow down succeeding lookups by one extra Hash cmp&and..usually
|
||||
# just a few clock cycles, generally worth it for any non-integer-like A.
|
||||
if s.data[h].hcode == hc and s.data[h].key == key: # compare hc THEN key
|
||||
return h
|
||||
|
|
@ -148,10 +148,10 @@ template rawInsertImpl() {.dirty.} =
|
|||
data[h].key = key
|
||||
data[h].hcode = hc
|
||||
|
||||
proc rawGetKnownHC[A](s: HashSet[A], key: A, hc: THash): int {.inline.} =
|
||||
proc rawGetKnownHC[A](s: HashSet[A], key: A, hc: Hash): int {.inline.} =
|
||||
rawGetKnownHCImpl()
|
||||
|
||||
proc rawGet[A](s: HashSet[A], key: A, hc: var THash): int {.inline.} =
|
||||
proc rawGet[A](s: HashSet[A], key: A, hc: var Hash): int {.inline.} =
|
||||
rawGetImpl()
|
||||
|
||||
proc mget*[A](s: var HashSet[A], key: A): var A =
|
||||
|
|
@ -160,7 +160,7 @@ proc mget*[A](s: var HashSet[A], key: A): var A =
|
|||
## when one overloaded 'hash' and '==' but still needs reference semantics
|
||||
## for sharing.
|
||||
assert s.isValid, "The set needs to be initialized."
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var index = rawGet(s, key, hc)
|
||||
if index >= 0: result = s.data[index].key
|
||||
else: raise newException(KeyError, "key not found: " & $key)
|
||||
|
|
@ -178,12 +178,12 @@ proc contains*[A](s: HashSet[A], key: A): bool =
|
|||
## values.excl(2)
|
||||
## assert(not values.contains(2))
|
||||
assert s.isValid, "The set needs to be initialized."
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var index = rawGet(s, key, hc)
|
||||
result = index >= 0
|
||||
|
||||
proc rawInsert[A](s: var HashSet[A], data: var KeyValuePairSeq[A], key: A,
|
||||
hc: THash, h: THash) =
|
||||
hc: Hash, h: Hash) =
|
||||
rawInsertImpl()
|
||||
|
||||
proc enlarge[A](s: var HashSet[A]) =
|
||||
|
|
@ -196,7 +196,7 @@ proc enlarge[A](s: var HashSet[A]) =
|
|||
rawInsert(s, s.data, n[i].key, n[i].hcode, j)
|
||||
|
||||
template inclImpl() {.dirty.} =
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var index = rawGet(s, key, hc)
|
||||
if index < 0:
|
||||
if mustRehash(len(s.data), s.counter):
|
||||
|
|
@ -206,7 +206,7 @@ template inclImpl() {.dirty.} =
|
|||
inc(s.counter)
|
||||
|
||||
template containsOrInclImpl() {.dirty.} =
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var index = rawGet(s, key, hc)
|
||||
if index >= 0:
|
||||
result = true
|
||||
|
|
@ -261,7 +261,7 @@ proc excl*[A](s: var HashSet[A], key: A) =
|
|||
## s.excl(2)
|
||||
## assert s.len == 3
|
||||
assert s.isValid, "The set needs to be initialized."
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var i = rawGet(s, key, hc)
|
||||
var msk = high(s.data)
|
||||
if i >= 0:
|
||||
|
|
@ -323,7 +323,7 @@ proc init*[A](s: var HashSet[A], initialSize=64) =
|
|||
## existing values and calling `excl() <#excl,TSet[A],A>`_ on them. Example:
|
||||
##
|
||||
## .. code-block ::
|
||||
## var a: TSet[int]
|
||||
## var a: Set[int]
|
||||
## a.init(4)
|
||||
## a.incl(2)
|
||||
## a.init
|
||||
|
|
@ -552,7 +552,7 @@ proc map*[A, B](data: HashSet[A], op: proc (x: A): B {.closure.}): HashSet[B] =
|
|||
|
||||
type
|
||||
OrderedKeyValuePair[A] = tuple[
|
||||
hcode: THash, next: int, key: A]
|
||||
hcode: Hash, next: int, key: A]
|
||||
OrderedKeyValuePairSeq[A] = seq[OrderedKeyValuePair[A]]
|
||||
OrderedSet* {.myShallow.}[A] = object ## \
|
||||
## A generic hash set that remembers insertion order.
|
||||
|
|
@ -574,7 +574,7 @@ proc isValid*[A](s: OrderedSet[A]): bool =
|
|||
## correctly initialized. Example:
|
||||
##
|
||||
## .. code-block::
|
||||
## proc saveTarotCards(cards: TOrderedSet[int]) =
|
||||
## proc saveTarotCards(cards: OrderedSet[int]) =
|
||||
## assert cards.isValid, "Pass an initialized set!"
|
||||
## # Do stuff here, may crash in release builds!
|
||||
result = not s.data.isNil
|
||||
|
|
@ -588,7 +588,7 @@ proc len*[A](s: OrderedSet[A]): int {.inline.} =
|
|||
##
|
||||
## .. code-block::
|
||||
##
|
||||
## var values: TOrderedSet[int]
|
||||
## var values: OrderedSet[int]
|
||||
## assert(not values.isValid)
|
||||
## assert values.len == 0
|
||||
result = s.counter
|
||||
|
|
@ -629,10 +629,10 @@ iterator items*[A](s: OrderedSet[A]): A =
|
|||
forAllOrderedPairs:
|
||||
yield s.data[h].key
|
||||
|
||||
proc rawGetKnownHC[A](s: OrderedSet[A], key: A, hc: THash): int {.inline.} =
|
||||
proc rawGetKnownHC[A](s: OrderedSet[A], key: A, hc: Hash): int {.inline.} =
|
||||
rawGetKnownHCImpl()
|
||||
|
||||
proc rawGet[A](s: OrderedSet[A], key: A, hc: var THash): int {.inline.} =
|
||||
proc rawGet[A](s: OrderedSet[A], key: A, hc: var Hash): int {.inline.} =
|
||||
rawGetImpl()
|
||||
|
||||
proc contains*[A](s: OrderedSet[A], key: A): bool =
|
||||
|
|
@ -646,12 +646,12 @@ proc contains*[A](s: OrderedSet[A], key: A): bool =
|
|||
## values.incl(2)
|
||||
## assert values.contains(2)
|
||||
assert s.isValid, "The set needs to be initialized."
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var index = rawGet(s, key, hc)
|
||||
result = index >= 0
|
||||
|
||||
proc rawInsert[A](s: var OrderedSet[A], data: var OrderedKeyValuePairSeq[A],
|
||||
key: A, hc: THash, h: THash) =
|
||||
key: A, hc: Hash, h: Hash) =
|
||||
rawInsertImpl()
|
||||
data[h].next = -1
|
||||
if s.first < 0: s.first = h
|
||||
|
|
@ -729,7 +729,7 @@ proc init*[A](s: var OrderedSet[A], initialSize=64) =
|
|||
## from an ordered hash set. Example:
|
||||
##
|
||||
## .. code-block ::
|
||||
## var a: TOrderedSet[int]
|
||||
## var a: OrderedSet[int]
|
||||
## a.init(4)
|
||||
## a.incl(2)
|
||||
## a.init
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@
|
|||
##
|
||||
## Error: type mismatch: got (Person)
|
||||
## but expected one of:
|
||||
## hashes.hash(x: openarray[A]): THash
|
||||
## hashes.hash(x: int): THash
|
||||
## hashes.hash(x: float): THash
|
||||
## hashes.hash(x: openarray[A]): Hash
|
||||
## hashes.hash(x: int): Hash
|
||||
## hashes.hash(x: float): Hash
|
||||
## …
|
||||
##
|
||||
## What is happening here is that the types used for table keys require to have
|
||||
## a ``hash()`` proc which will convert them to a `THash <hashes.html#THash>`_
|
||||
## a ``hash()`` proc which will convert them to a `Hash <hashes.html#Hash>`_
|
||||
## value, and the compiler is listing all the hash functions it knows.
|
||||
## Additionally there has to be a ``==`` operator that provides the same
|
||||
## semantics as its corresponding ``hash`` proc.
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
## Person = object
|
||||
## firstName, lastName: string
|
||||
##
|
||||
## proc hash(x: Person): THash =
|
||||
## proc hash(x: Person): Hash =
|
||||
## ## Piggyback on the already available string hash proc.
|
||||
## ##
|
||||
## ## Without this proc nothing works!
|
||||
|
|
@ -71,7 +71,7 @@ import
|
|||
{.pragma: myShallow.}
|
||||
|
||||
type
|
||||
KeyValuePair[A, B] = tuple[hcode: THash, key: A, val: B]
|
||||
KeyValuePair[A, B] = tuple[hcode: Hash, key: A, val: B]
|
||||
KeyValuePairSeq[A, B] = seq[KeyValuePair[A, B]]
|
||||
Table* {.myShallow.}[A, B] = object ## generic hash table
|
||||
data: KeyValuePairSeq[A, B]
|
||||
|
|
@ -85,10 +85,10 @@ when not defined(nimhygiene):
|
|||
|
||||
# hcode for real keys cannot be zero. hcode==0 signifies an empty slot. These
|
||||
# two procs retain clarity of that encoding without the space cost of an enum.
|
||||
proc isEmpty(hcode: THash): bool {.inline.} =
|
||||
proc isEmpty(hcode: Hash): bool {.inline.} =
|
||||
result = hcode == 0
|
||||
|
||||
proc isFilled(hcode: THash): bool {.inline.} =
|
||||
proc isFilled(hcode: Hash): bool {.inline.} =
|
||||
result = hcode != 0
|
||||
|
||||
proc len*[A, B](t: Table[A, B]): int =
|
||||
|
|
@ -137,15 +137,15 @@ proc rightSize*(count: Natural): int {.inline.} =
|
|||
## Internally, we want mustRehash(rightSize(x), x) == false.
|
||||
result = nextPowerOfTwo(count * 3 div 2 + 4)
|
||||
|
||||
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
||||
proc nextTry(h, maxHash: Hash): Hash {.inline.} =
|
||||
result = (h + 1) and maxHash
|
||||
|
||||
template rawGetKnownHCImpl() {.dirty.} =
|
||||
var h: THash = hc and high(t.data) # start with real hash value
|
||||
var h: Hash = hc and high(t.data) # start with real hash value
|
||||
while isFilled(t.data[h].hcode):
|
||||
# Compare hc THEN key with boolean short circuit. This makes the common case
|
||||
# zero ==key's for missing (e.g.inserts) and exactly one ==key for present.
|
||||
# It does slow down succeeding lookups by one extra THash cmp&and..usually
|
||||
# It does slow down succeeding lookups by one extra Hash cmp&and..usually
|
||||
# just a few clock cycles, generally worth it for any non-integer-like A.
|
||||
if t.data[h].hcode == hc and t.data[h].key == key:
|
||||
return h
|
||||
|
|
@ -162,7 +162,7 @@ template rawGetDeepImpl() {.dirty.} = # Search algo for unconditional add
|
|||
hc = hash(key)
|
||||
if hc == 0:
|
||||
hc = 314159265
|
||||
var h: THash = hc and high(t.data)
|
||||
var h: Hash = hc and high(t.data)
|
||||
while isFilled(t.data[h].hcode):
|
||||
h = nextTry(h, high(t.data))
|
||||
result = h
|
||||
|
|
@ -172,13 +172,13 @@ template rawInsertImpl() {.dirty.} =
|
|||
data[h].val = val
|
||||
data[h].hcode = hc
|
||||
|
||||
proc rawGetKnownHC[A, B](t: Table[A, B], key: A, hc: THash): int {.inline.} =
|
||||
proc rawGetKnownHC[A, B](t: Table[A, B], key: A, hc: Hash): int {.inline.} =
|
||||
rawGetKnownHCImpl()
|
||||
|
||||
proc rawGetDeep[A, B](t: Table[A, B], key: A, hc: var THash): int {.inline.} =
|
||||
proc rawGetDeep[A, B](t: Table[A, B], key: A, hc: var Hash): int {.inline.} =
|
||||
rawGetDeepImpl()
|
||||
|
||||
proc rawGet[A, B](t: Table[A, B], key: A, hc: var THash): int {.inline.} =
|
||||
proc rawGet[A, B](t: Table[A, B], key: A, hc: var Hash): int {.inline.} =
|
||||
rawGetImpl()
|
||||
|
||||
proc `[]`*[A, B](t: Table[A, B], key: A): B =
|
||||
|
|
@ -186,14 +186,14 @@ proc `[]`*[A, B](t: Table[A, B], key: A): B =
|
|||
## default empty value for the type `B` is returned
|
||||
## and no exception is raised. One can check with ``hasKey`` whether the key
|
||||
## exists.
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var index = rawGet(t, key, hc)
|
||||
if index >= 0: result = t.data[index].val
|
||||
|
||||
proc mget*[A, B](t: var Table[A, B], key: A): var B =
|
||||
## retrieves the value at ``t[key]``. The value can be modified.
|
||||
## If `key` is not in `t`, the ``KeyError`` exception is raised.
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var index = rawGet(t, key, hc)
|
||||
if index >= 0: result = t.data[index].val
|
||||
else:
|
||||
|
|
@ -204,7 +204,7 @@ proc mget*[A, B](t: var Table[A, B], key: A): var B =
|
|||
|
||||
iterator allValues*[A, B](t: Table[A, B]; key: A): B =
|
||||
## iterates over any value in the table `t` that belongs to the given `key`.
|
||||
var h: THash = hash(key) and high(t.data)
|
||||
var h: Hash = hash(key) and high(t.data)
|
||||
while isFilled(t.data[h].hcode):
|
||||
if t.data[h].key == key:
|
||||
yield t.data[h].val
|
||||
|
|
@ -212,7 +212,7 @@ iterator allValues*[A, B](t: Table[A, B]; key: A): B =
|
|||
|
||||
proc hasKey*[A, B](t: Table[A, B], key: A): bool =
|
||||
## returns true iff `key` is in the table `t`.
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
result = rawGet(t, key, hc) >= 0
|
||||
|
||||
proc contains*[A, B](t: Table[A, B], key: A): bool =
|
||||
|
|
@ -220,7 +220,7 @@ proc contains*[A, B](t: Table[A, B], key: A): bool =
|
|||
return hasKey[A, B](t, key)
|
||||
|
||||
proc rawInsert[A, B](t: var Table[A, B], data: var KeyValuePairSeq[A, B],
|
||||
key: A, val: B, hc: THash, h: THash) =
|
||||
key: A, val: B, hc: Hash, h: Hash) =
|
||||
rawInsertImpl()
|
||||
|
||||
proc enlarge[A, B](t: var Table[A, B]) =
|
||||
|
|
@ -234,7 +234,7 @@ proc enlarge[A, B](t: var Table[A, B]) =
|
|||
|
||||
template addImpl() {.dirty.} =
|
||||
if mustRehash(len(t.data), t.counter): enlarge(t)
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var j = rawGetDeep(t, key, hc)
|
||||
rawInsert(t, t.data, key, val, hc, j)
|
||||
inc(t.counter)
|
||||
|
|
@ -248,19 +248,19 @@ template maybeRehashPutImpl() {.dirty.} =
|
|||
inc(t.counter)
|
||||
|
||||
template putImpl() {.dirty.} =
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var index = rawGet(t, key, hc)
|
||||
if index >= 0: t.data[index].val = val
|
||||
else: maybeRehashPutImpl()
|
||||
|
||||
template mgetOrPutImpl() {.dirty.} =
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var index = rawGet(t, key, hc)
|
||||
if index < 0: maybeRehashPutImpl() # not present: insert (flipping index)
|
||||
result = t.data[index].val # either way return modifiable val
|
||||
|
||||
template hasKeyOrPutImpl() {.dirty.} =
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var index = rawGet(t, key, hc)
|
||||
if index < 0:
|
||||
result = false
|
||||
|
|
@ -291,7 +291,7 @@ template doWhile(a: expr, b: stmt): stmt =
|
|||
|
||||
proc del*[A, B](t: var Table[A, B], key: A) =
|
||||
## deletes `key` from hash table `t`.
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var i = rawGet(t, key, hc)
|
||||
let msk = high(t.data)
|
||||
if i >= 0:
|
||||
|
|
@ -460,7 +460,7 @@ proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): TableRef[C, B]
|
|||
|
||||
type
|
||||
OrderedKeyValuePair[A, B] = tuple[
|
||||
hcode: THash, next: int, key: A, val: B]
|
||||
hcode: Hash, next: int, key: A, val: B]
|
||||
OrderedKeyValuePairSeq[A, B] = seq[OrderedKeyValuePair[A, B]]
|
||||
OrderedTable* {.
|
||||
myShallow.}[A, B] = object ## table that remembers insertion order
|
||||
|
|
@ -509,13 +509,13 @@ iterator mvalues*[A, B](t: var OrderedTable[A, B]): var B =
|
|||
forAllOrderedPairs:
|
||||
yield t.data[h].val
|
||||
|
||||
proc rawGetKnownHC[A, B](t: OrderedTable[A, B], key: A, hc: THash): int =
|
||||
proc rawGetKnownHC[A, B](t: OrderedTable[A, B], key: A, hc: Hash): int =
|
||||
rawGetKnownHCImpl()
|
||||
|
||||
proc rawGetDeep[A, B](t: OrderedTable[A, B], key: A, hc: var THash): int {.inline.} =
|
||||
proc rawGetDeep[A, B](t: OrderedTable[A, B], key: A, hc: var Hash): int {.inline.} =
|
||||
rawGetDeepImpl()
|
||||
|
||||
proc rawGet[A, B](t: OrderedTable[A, B], key: A, hc: var THash): int =
|
||||
proc rawGet[A, B](t: OrderedTable[A, B], key: A, hc: var Hash): int =
|
||||
rawGetImpl()
|
||||
|
||||
proc `[]`*[A, B](t: OrderedTable[A, B], key: A): B =
|
||||
|
|
@ -523,21 +523,21 @@ proc `[]`*[A, B](t: OrderedTable[A, B], key: A): B =
|
|||
## default empty value for the type `B` is returned
|
||||
## and no exception is raised. One can check with ``hasKey`` whether the key
|
||||
## exists.
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var index = rawGet(t, key, hc)
|
||||
if index >= 0: result = t.data[index].val
|
||||
|
||||
proc mget*[A, B](t: var OrderedTable[A, B], key: A): var B =
|
||||
## retrieves the value at ``t[key]``. The value can be modified.
|
||||
## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
var index = rawGet(t, key, hc)
|
||||
if index >= 0: result = t.data[index].val
|
||||
else: raise newException(KeyError, "key not found: " & $key)
|
||||
|
||||
proc hasKey*[A, B](t: OrderedTable[A, B], key: A): bool =
|
||||
## returns true iff `key` is in the table `t`.
|
||||
var hc: THash
|
||||
var hc: Hash
|
||||
result = rawGet(t, key, hc) >= 0
|
||||
|
||||
proc contains*[A, B](t: OrderedTable[A, B], key: A): bool =
|
||||
|
|
@ -546,7 +546,7 @@ proc contains*[A, B](t: OrderedTable[A, B], key: A): bool =
|
|||
|
||||
proc rawInsert[A, B](t: var OrderedTable[A, B],
|
||||
data: var OrderedKeyValuePairSeq[A, B],
|
||||
key: A, val: B, hc: THash, h: THash) =
|
||||
key: A, val: B, hc: Hash, h: Hash) =
|
||||
rawInsertImpl()
|
||||
data[h].next = -1
|
||||
if t.first < 0: t.first = h
|
||||
|
|
@ -796,7 +796,7 @@ iterator mvalues*[A](t: CountTable[A]): var int =
|
|||
if t.data[h].val != 0: yield t.data[h].val
|
||||
|
||||
proc rawGet[A](t: CountTable[A], key: A): int =
|
||||
var h: THash = hash(key) and high(t.data) # start with real hash value
|
||||
var h: Hash = hash(key) and high(t.data) # start with real hash value
|
||||
while t.data[h].val != 0:
|
||||
if t.data[h].key == key: return h
|
||||
h = nextTry(h, high(t.data))
|
||||
|
|
@ -826,7 +826,7 @@ proc contains*[A](t: CountTable[A], key: A): bool =
|
|||
|
||||
proc rawInsert[A](t: CountTable[A], data: var seq[tuple[key: A, val: int]],
|
||||
key: A, val: int) =
|
||||
var h: THash = hash(key) and high(data)
|
||||
var h: Hash = hash(key) and high(data)
|
||||
while data[h].val != 0: h = nextTry(h, high(data))
|
||||
data[h].key = key
|
||||
data[h].val = val
|
||||
|
|
@ -1032,7 +1032,7 @@ when isMainModule:
|
|||
Person = object
|
||||
firstName, lastName: string
|
||||
|
||||
proc hash(x: Person): THash =
|
||||
proc hash(x: Person): Hash =
|
||||
## Piggyback on the already available string hash proc.
|
||||
##
|
||||
## Without this proc nothing works!
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue