* fix #13496 handle tombstones * add test * more tests * fix #13504; add SharedTable tests * fix #https://github.com/nim-lang/Nim/issues/13505 intsets.missingOrExcl silently gave wrong results sometimes * add test for tintsets
This commit is contained in:
parent
9a93f73983
commit
42dad3a836
9 changed files with 296 additions and 41 deletions
|
|
@ -330,6 +330,15 @@ proc excl*(s: var IntSet, other: IntSet) =
|
|||
|
||||
for item in other: excl(s, item)
|
||||
|
||||
proc len*(s: IntSet): int {.inline.} =
|
||||
## Returns the number of elements in `s`.
|
||||
if s.elems < s.a.len:
|
||||
result = s.elems
|
||||
else:
|
||||
result = 0
|
||||
for _ in s:
|
||||
inc(result)
|
||||
|
||||
proc missingOrExcl*(s: var IntSet, key: int): bool =
|
||||
## Excludes `key` in the set `s` and tells if `key` was already missing from `s`.
|
||||
##
|
||||
|
|
@ -348,9 +357,9 @@ proc missingOrExcl*(s: var IntSet, key: int): bool =
|
|||
assert a.missingOrExcl(5) == false
|
||||
assert a.missingOrExcl(5) == true
|
||||
|
||||
var count = s.elems
|
||||
var count = s.len
|
||||
exclImpl(s, key)
|
||||
result = count == s.elems
|
||||
result = count == s.len
|
||||
|
||||
proc clear*(result: var IntSet) =
|
||||
## Clears the IntSet back to an empty state.
|
||||
|
|
@ -514,15 +523,6 @@ proc disjoint*(s1, s2: IntSet): bool =
|
|||
return false
|
||||
return true
|
||||
|
||||
proc len*(s: IntSet): int {.inline.} =
|
||||
## Returns the number of elements in `s`.
|
||||
if s.elems < s.a.len:
|
||||
result = s.elems
|
||||
else:
|
||||
result = 0
|
||||
for _ in s:
|
||||
inc(result)
|
||||
|
||||
proc card*(s: IntSet): int {.inline.} =
|
||||
## Alias for `len() <#len,IntSet>`_.
|
||||
result = s.len()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ proc enlarge[A](s: var HashSet[A]) =
|
|||
newSeq(n, len(s.data) * growthFactor)
|
||||
swap(s.data, n) # n is now old seq
|
||||
for i in countup(0, high(n)):
|
||||
if isFilled(n[i].hcode):
|
||||
if isFilledAndValid(n[i].hcode):
|
||||
var j = -1 - rawGetKnownHC(s, n[i].key, n[i].hcode)
|
||||
rawInsert(s, s.data, n[i].key, n[i].hcode, j)
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ proc enlarge[A](s: var OrderedSet[A]) =
|
|||
swap(s.data, n)
|
||||
while h >= 0:
|
||||
var nxt = n[h].next
|
||||
if isFilled(n[h].hcode):
|
||||
if isFilled(n[h].hcode): # should be isFilledAndValid once tombstones are used
|
||||
var j = -1 - rawGetKnownHC(s, n[h].key, n[h].hcode)
|
||||
rawInsert(s, s.data, n[h].key, n[h].hcode, j)
|
||||
h = nxt
|
||||
|
|
@ -130,7 +130,7 @@ proc exclImpl[A](s: var OrderedSet[A], key: A): bool {.inline.} =
|
|||
result = true
|
||||
while h >= 0:
|
||||
var nxt = n[h].next
|
||||
if isFilled(n[h].hcode):
|
||||
if isFilled(n[h].hcode): # should be isFilledAndValid once tombstones are used
|
||||
if n[h].hcode == hc and n[h].key == key:
|
||||
dec s.counter
|
||||
result = false
|
||||
|
|
|
|||
|
|
@ -206,6 +206,11 @@ proc del*[A, B](t: var SharedTable[A, B], key: A) =
|
|||
withLock t:
|
||||
delImpl()
|
||||
|
||||
proc len*[A, B](t: var SharedTable[A, B]): int =
|
||||
## number of elements in `t`
|
||||
withLock t:
|
||||
result = t.counter
|
||||
|
||||
proc init*[A, B](t: var SharedTable[A, B], initialSize = 64) =
|
||||
## creates a new hash table that is empty.
|
||||
##
|
||||
|
|
|
|||
|
|
@ -107,13 +107,23 @@ template clearImpl() {.dirty.} =
|
|||
t.data[i].val = default(type(t.data[i].val))
|
||||
t.counter = 0
|
||||
|
||||
template ctAnd(a, b): bool =
|
||||
# pending https://github.com/nim-lang/Nim/issues/13502
|
||||
when a:
|
||||
when b: true
|
||||
else: false
|
||||
else: false
|
||||
|
||||
template initImpl(result: typed, size: int) =
|
||||
assert isPowerOfTwo(size)
|
||||
result.counter = 0
|
||||
newSeq(result.data, size)
|
||||
when compiles(result.first):
|
||||
result.first = -1
|
||||
result.last = -1
|
||||
when ctAnd(declared(SharedTable), type(result) is SharedTable):
|
||||
init(result, size)
|
||||
else:
|
||||
assert isPowerOfTwo(size)
|
||||
result.counter = 0
|
||||
newSeq(result.data, size)
|
||||
when compiles(result.first):
|
||||
result.first = -1
|
||||
result.last = -1
|
||||
|
||||
template insertImpl() = # for CountTable
|
||||
checkIfInitialized()
|
||||
|
|
|
|||
|
|
@ -1118,7 +1118,7 @@ iterator pairs*[A, B](t: TableRef[A, B]): (A, B) =
|
|||
## # value: [1, 5, 7, 9]
|
||||
let L = len(t)
|
||||
for h in 0 .. high(t.data):
|
||||
if isFilled(t.data[h].hcode):
|
||||
if isFilledAndValid(t.data[h].hcode):
|
||||
yield (t.data[h].key, t.data[h].val)
|
||||
assert(len(t) == L, "the length of the table changed while iterating over it")
|
||||
|
||||
|
|
@ -1140,7 +1140,7 @@ iterator mpairs*[A, B](t: TableRef[A, B]): (A, var B) =
|
|||
|
||||
let L = len(t)
|
||||
for h in 0 .. high(t.data):
|
||||
if isFilled(t.data[h].hcode):
|
||||
if isFilledAndValid(t.data[h].hcode):
|
||||
yield (t.data[h].key, t.data[h].val)
|
||||
assert(len(t) == L, "the length of the table changed while iterating over it")
|
||||
|
||||
|
|
@ -1161,7 +1161,7 @@ iterator keys*[A, B](t: TableRef[A, B]): A =
|
|||
|
||||
let L = len(t)
|
||||
for h in 0 .. high(t.data):
|
||||
if isFilled(t.data[h].hcode):
|
||||
if isFilledAndValid(t.data[h].hcode):
|
||||
yield t.data[h].key
|
||||
assert(len(t) == L, "the length of the table changed while iterating over it")
|
||||
|
||||
|
|
@ -1182,7 +1182,7 @@ iterator values*[A, B](t: TableRef[A, B]): B =
|
|||
|
||||
let L = len(t)
|
||||
for h in 0 .. high(t.data):
|
||||
if isFilled(t.data[h].hcode):
|
||||
if isFilledAndValid(t.data[h].hcode):
|
||||
yield t.data[h].val
|
||||
assert(len(t) == L, "the length of the table changed while iterating over it")
|
||||
|
||||
|
|
@ -1203,7 +1203,7 @@ iterator mvalues*[A, B](t: TableRef[A, B]): var B =
|
|||
|
||||
let L = len(t)
|
||||
for h in 0 .. high(t.data):
|
||||
if isFilled(t.data[h].hcode):
|
||||
if isFilledAndValid(t.data[h].hcode):
|
||||
yield t.data[h].val
|
||||
assert(len(t) == L, "the length of the table changed while iterating over it")
|
||||
|
||||
|
|
@ -1282,6 +1282,10 @@ template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} =
|
|||
var h = t.first
|
||||
while h >= 0:
|
||||
var nxt = t.data[h].next
|
||||
# For OrderedTable/OrderedTableRef, isFilled is ok because `del` is O(n)
|
||||
# and doesn't create tombsones, but if it does start using tombstones,
|
||||
# carefully replace `isFilled` by `isFilledAndValid` as appropriate for these
|
||||
# table types only, ditto with `OrderedSet`.
|
||||
if isFilled(t.data[h].hcode):
|
||||
yieldStmt
|
||||
h = nxt
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue