diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2017-09-22 13:29:53 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-09-22 13:29:53 +0200 |
commit | 240953411e4a170fd0d17279bc560dda1d0a960a (patch) | |
tree | 58caaf910c9ab59d9869f0b18766a9f99e26788f /lib | |
parent | 5298a72f34ad2eb3774d6d70bd3176773cc0651f (diff) | |
parent | 92d67262fb4969d6ecd2f122c9ee14155abf75c3 (diff) | |
download | Nim-240953411e4a170fd0d17279bc560dda1d0a960a.tar.gz |
Merge branch 'devel' of github.com:nim-lang/Nim into devel
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/collections/sets.nim | 98 | ||||
-rw-r--r-- | lib/pure/nativesockets.nim | 4 | ||||
-rw-r--r-- | lib/system.nim | 2 |
3 files changed, 97 insertions, 7 deletions
diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index d51a5c388..dbdf17514 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -287,8 +287,6 @@ proc exclImpl[A](s: var HashSet[A], key: A) : bool {. inline .} = if i >= 0: result = false - s.data[i].hcode = 0 - s.data[i].key = default(type(s.data[i].key)) dec(s.counter) while true: # KnuthV3 Algo6.4R adapted for i=i+1 instead of i=i-1 var j = i # The correctness of this depends on (h+1) in nextTry, @@ -300,7 +298,7 @@ proc exclImpl[A](s: var HashSet[A], key: A) : bool {. inline .} = if isEmpty(s.data[i].hcode): # end of collision cluster; So all done return r = s.data[i].hcode and msk # "home" location of key@i - shallowCopy(s.data[j], s.data[i]) # data[j] will be marked EMPTY next loop + shallowCopy(s.data[j], s.data[i]) # data[i] will be marked EMPTY next loop proc missingOrExcl*[A](s: var HashSet[A], key: A): bool = ## Excludes `key` in the set `s` and tells if `key` was removed from `s`. @@ -662,9 +660,12 @@ proc card*[A](s: OrderedSet[A]): int {.inline.} = template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} = var h = s.first + var idx = 0 while h >= 0: var nxt = s.data[h].next - if isFilled(s.data[h].hcode): yieldStmt + if isFilled(s.data[h].hcode): + yieldStmt + inc(idx) h = nxt iterator items*[A](s: OrderedSet[A]): A = @@ -689,6 +690,11 @@ iterator items*[A](s: OrderedSet[A]): A = forAllOrderedPairs: yield s.data[h].key +iterator pairs*[A](s: OrderedSet[A]): tuple[a: int, b: A] = + assert s.isValid, "The set needs to be initialized" + forAllOrderedPairs: + yield (idx, s.data[h].key) + proc rawGetKnownHC[A](s: OrderedSet[A], key: A, hc: Hash): int {.inline.} = rawGetKnownHCImpl() @@ -760,6 +766,67 @@ proc incl*[A](s: var HashSet[A], other: OrderedSet[A]) = assert other.isValid, "The set `other` needs to be initialized." for item in other: incl(s, item) +proc exclImpl[A](s: var OrderedSet[A], key: A) : bool {. inline .} = + assert s.isValid, "The set needs to be initialized." + var hc: Hash + var i = rawGet(s, key, hc) + var msk = high(s.data) + result = true + + if i >= 0: + result = false + # Fix ordering + if s.first == i: + s.first = s.data[i].next + else: + var itr = s.first + while true: + if (s.data[itr].next == i): + s.data[itr].next = s.data[i].next + if s.last == i: + s.last = itr + break + itr = s.data[itr].next + + dec(s.counter) + while true: # KnuthV3 Algo6.4R adapted for i=i+1 instead of i=i-1 + var j = i # The correctness of this depends on (h+1) in nextTry, + var r = j # though may be adaptable to other simple sequences. + s.data[i].hcode = 0 # mark current EMPTY + s.data[i].key = default(type(s.data[i].key)) + s.data[i].next = 0 + doWhile((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)): + i = (i + 1) and msk # increment mod table size + if isEmpty(s.data[i].hcode): # end of collision cluster; So all done + return + r = s.data[i].hcode and msk # "home" location of key@i + shallowCopy(s.data[j], s.data[i]) # data[i] will be marked EMPTY next loop + +proc missingOrExcl*[A](s: var OrderedSet[A], key: A): bool = + ## Excludes `key` in the set `s` and tells if `key` was removed from `s`. Efficiency: O(n). + ## + ## The difference with regards to the `excl() <#excl,TOrderedSet[A],A>`_ proc is + ## that this proc returns `true` if `key` was not present in `s`. Example: + ## + ## .. code-block:: + ## var s = toOrderedSet([2, 3, 6, 7]) + ## assert s.missingOrExcl(4) == true + ## assert s.missingOrExcl(6) == false + exclImpl(s, key) + + +proc excl*[A](s: var OrderedSet[A], key: A) = + ## Excludes `key` from the set `s`. Efficiency: O(n). + ## + ## This doesn't do anything if `key` is not found in `s`. Example: + ## + ## .. code-block:: + ## var s = toOrderedSet([2, 3, 6, 7]) + ## s.excl(2) + ## s.excl(2) + ## assert s.len == 3 + discard exclImpl(s, key) + proc containsOrIncl*[A](s: var OrderedSet[A], key: A): bool = ## Includes `key` in the set `s` and tells if `key` was added to `s`. ## @@ -986,6 +1053,24 @@ when isMainModule and not defined(release): assert a.len == b.card assert a.len == 2 + block setPairsIterator: + var s = toOrderedSet([1, 3, 5, 7]) + var items = newSeq[tuple[a: int, b: int]]() + for idx, item in s: items.add((idx, item)) + assert items == @[(0, 1), (1, 3), (2, 5), (3, 7)] + + block exclusions: + var s = toOrderedSet([1, 2, 3, 6, 7, 4]) + + s.excl(3) + s.excl(3) + s.excl(1) + s.excl(4) + + var items = newSeq[int]() + for item in s: items.add item + assert items == @[2, 6, 7] + #block orderedSetIterator: # var a = initOrderedSet[int]() # for value in [9, 2, 1, 5, 1, 8, 4, 2]: @@ -1030,6 +1115,11 @@ when isMainModule and not defined(release): if s <= i or mustRehash(s, i): echo "performance issue: rightSize() will not elide enlarge() at ", i + block missingOrExcl: + var s = toOrderedSet([2, 3, 6, 7]) + assert s.missingOrExcl(4) == true + assert s.missingOrExcl(6) == false + when not defined(testing): echo "Micro tests run successfully." diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim index 1a62c0bf6..98fc62a3b 100644 --- a/lib/pure/nativesockets.nim +++ b/lib/pure/nativesockets.nim @@ -498,7 +498,7 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) = # Cannot use INET6_ADDRSTRLEN here, because it's a C define. var buf: array[64, char] if inet_ntop(name.sin6_family.cint, - addr name, buf.cstring, sizeof(buf).int32).isNil: + addr name.sin6_addr, buf.cstring, sizeof(buf).int32).isNil: raiseOSError(osLastError()) result = ($buf, Port(nativesockets.ntohs(name.sin6_port))) else: @@ -534,7 +534,7 @@ proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) = # Cannot use INET6_ADDRSTRLEN here, because it's a C define. var buf: array[64, char] if inet_ntop(name.sin6_family.cint, - addr name, buf.cstring, sizeof(buf).int32).isNil: + addr name.sin6_addr, buf.cstring, sizeof(buf).int32).isNil: raiseOSError(osLastError()) result = ($buf, Port(nativesockets.ntohs(name.sin6_port))) else: diff --git a/lib/system.nim b/lib/system.nim index a4460570a..efffeaeca 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -718,7 +718,7 @@ proc len*[TOpenArray: openArray|varargs](x: TOpenArray): int {. magic: "LengthOpenArray", noSideEffect.} proc len*(x: string): int {.magic: "LengthStr", noSideEffect.} proc len*(x: cstring): int {.magic: "LengthStr", noSideEffect.} -proc len*[I, T](x: array[I, T]): int {.magic: "LengthArray", noSideEffect.} +proc len*(x: (type array)|array): int {.magic: "LengthArray", noSideEffect.} proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.} ## returns the length of an array, an openarray, a sequence or a string. ## This is roughly the same as ``high(T)-low(T)+1``, but its resulting type is |