add more functionality from sets to intsets (#7185)
* add more functionality from sets to intsets * remove -+- * < and == performance * don't hardcode s.a.len * remove shortcuts from < and ==
This commit is contained in:
parent
4c702d5ab2
commit
df4f707743
1 changed files with 156 additions and 21 deletions
|
|
@ -108,6 +108,28 @@ proc contains*(s: IntSet, key: int): bool =
|
||||||
else:
|
else:
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
|
iterator items*(s: IntSet): int {.inline.} =
|
||||||
|
## iterates over any included element of `s`.
|
||||||
|
if s.elems <= s.a.len:
|
||||||
|
for i in 0..<s.elems:
|
||||||
|
yield s.a[i]
|
||||||
|
else:
|
||||||
|
var r = s.head
|
||||||
|
while r != nil:
|
||||||
|
var i = 0
|
||||||
|
while i <= high(r.bits):
|
||||||
|
var w = r.bits[i]
|
||||||
|
# taking a copy of r.bits[i] here is correct, because
|
||||||
|
# modifying operations are not allowed during traversation
|
||||||
|
var j = 0
|
||||||
|
while w != 0: # test all remaining bits for zero
|
||||||
|
if (w and 1) != 0: # the bit is set!
|
||||||
|
yield (r.key shl TrunkShift) or (i shl IntShift +% j)
|
||||||
|
inc(j)
|
||||||
|
w = w shr 1
|
||||||
|
inc(i)
|
||||||
|
r = r.next
|
||||||
|
|
||||||
proc bitincl(s: var IntSet, key: int) {.inline.} =
|
proc bitincl(s: var IntSet, key: int) {.inline.} =
|
||||||
var t = intSetPut(s, `shr`(key, TrunkShift))
|
var t = intSetPut(s, `shr`(key, TrunkShift))
|
||||||
var u = key and TrunkMask
|
var u = key and TrunkMask
|
||||||
|
|
@ -131,6 +153,10 @@ proc incl*(s: var IntSet, key: int) =
|
||||||
# fall through:
|
# fall through:
|
||||||
bitincl(s, key)
|
bitincl(s, key)
|
||||||
|
|
||||||
|
proc incl*(s: var IntSet, other: IntSet) =
|
||||||
|
## Includes all elements from `other` into `s`.
|
||||||
|
for item in other: incl(s, item)
|
||||||
|
|
||||||
proc exclImpl(s: var IntSet, key: int) =
|
proc exclImpl(s: var IntSet, key: int) =
|
||||||
if s.elems <= s.a.len:
|
if s.elems <= s.a.len:
|
||||||
for i in 0..<s.elems:
|
for i in 0..<s.elems:
|
||||||
|
|
@ -149,6 +175,10 @@ proc excl*(s: var IntSet, key: int) =
|
||||||
## excludes `key` from the set `s`.
|
## excludes `key` from the set `s`.
|
||||||
exclImpl(s, key)
|
exclImpl(s, key)
|
||||||
|
|
||||||
|
proc excl*(s: var IntSet, other: IntSet) =
|
||||||
|
## Excludes all elements from `other` from `s`.
|
||||||
|
for item in other: excl(s, item)
|
||||||
|
|
||||||
proc missingOrExcl*(s: var IntSet, key: int) : bool =
|
proc missingOrExcl*(s: var IntSet, key: int) : bool =
|
||||||
## returns true if `s` does not contain `key`, otherwise
|
## returns true if `s` does not contain `key`, otherwise
|
||||||
## `key` is removed from `s` and false is returned.
|
## `key` is removed from `s` and false is returned.
|
||||||
|
|
@ -232,27 +262,77 @@ proc assign*(dest: var IntSet, src: IntSet) =
|
||||||
|
|
||||||
it = it.next
|
it = it.next
|
||||||
|
|
||||||
iterator items*(s: IntSet): int {.inline.} =
|
proc union*(s1, s2: IntSet): IntSet =
|
||||||
## iterates over any included element of `s`.
|
## Returns the union of the sets `s1` and `s2`.
|
||||||
if s.elems <= s.a.len:
|
result.assign(s1)
|
||||||
for i in 0..<s.elems:
|
incl(result, s2)
|
||||||
yield s.a[i]
|
|
||||||
|
proc intersection*(s1, s2: IntSet): IntSet =
|
||||||
|
## Returns the intersection of the sets `s1` and `s2`.
|
||||||
|
result = initIntSet()
|
||||||
|
for item in s1:
|
||||||
|
if contains(s2, item):
|
||||||
|
incl(result, item)
|
||||||
|
|
||||||
|
proc difference*(s1, s2: IntSet): IntSet =
|
||||||
|
## Returns the difference of the sets `s1` and `s2`.
|
||||||
|
result = initIntSet()
|
||||||
|
for item in s1:
|
||||||
|
if not contains(s2, item):
|
||||||
|
incl(result, item)
|
||||||
|
|
||||||
|
proc symmetricDifference*(s1, s2: IntSet): IntSet =
|
||||||
|
## Returns the symmetric difference of the sets `s1` and `s2`.
|
||||||
|
result.assign(s1)
|
||||||
|
for item in s2:
|
||||||
|
if containsOrIncl(result, item): excl(result, item)
|
||||||
|
|
||||||
|
proc `+`*(s1, s2: IntSet): IntSet {.inline.} =
|
||||||
|
## Alias for `union(s1, s2) <#union>`_.
|
||||||
|
result = union(s1, s2)
|
||||||
|
|
||||||
|
proc `*`*(s1, s2: IntSet): IntSet {.inline.} =
|
||||||
|
## Alias for `intersection(s1, s2) <#intersection>`_.
|
||||||
|
result = intersection(s1, s2)
|
||||||
|
|
||||||
|
proc `-`*(s1, s2: IntSet): IntSet {.inline.} =
|
||||||
|
## Alias for `difference(s1, s2) <#difference>`_.
|
||||||
|
result = difference(s1, s2)
|
||||||
|
|
||||||
|
proc disjoint*(s1, s2: IntSet): bool =
|
||||||
|
## Returns true iff the sets `s1` and `s2` have no items in common.
|
||||||
|
for item in s1:
|
||||||
|
if contains(s2, item):
|
||||||
|
return false
|
||||||
|
return true
|
||||||
|
|
||||||
|
proc len*(s: IntSet): int {.inline.} =
|
||||||
|
## Returns the number of keys in `s`.
|
||||||
|
if s.elems < s.a.len:
|
||||||
|
result = s.elems
|
||||||
else:
|
else:
|
||||||
var r = s.head
|
result = 0
|
||||||
while r != nil:
|
for _ in s:
|
||||||
var i = 0
|
inc(result)
|
||||||
while i <= high(r.bits):
|
|
||||||
var w = r.bits[i]
|
proc card*(s: IntSet): int {.inline.} =
|
||||||
# taking a copy of r.bits[i] here is correct, because
|
## alias for `len() <#len>` _.
|
||||||
# modifying operations are not allowed during traversation
|
result = s.len()
|
||||||
var j = 0
|
|
||||||
while w != 0: # test all remaining bits for zero
|
proc `<=`*(s1, s2: IntSet): bool =
|
||||||
if (w and 1) != 0: # the bit is set!
|
## Returns true iff `s1` is subset of `s2`.
|
||||||
yield (r.key shl TrunkShift) or (i shl IntShift +% j)
|
for item in s1:
|
||||||
inc(j)
|
if not s2.contains(item):
|
||||||
w = w shr 1
|
return false
|
||||||
inc(i)
|
return true
|
||||||
r = r.next
|
|
||||||
|
proc `<`*(s1, s2: IntSet): bool =
|
||||||
|
## Returns true iff `s1` is proper subset of `s2`.
|
||||||
|
return s1 <= s2 and not (s2 <= s1)
|
||||||
|
|
||||||
|
proc `==`*(s1, s2: IntSet): bool =
|
||||||
|
## Returns true if both `s` and `t` have the same members and set size.
|
||||||
|
return s1 <= s2 and s2 <= s1
|
||||||
|
|
||||||
template dollarImpl(): untyped =
|
template dollarImpl(): untyped =
|
||||||
result = "{"
|
result = "{"
|
||||||
|
|
@ -301,9 +381,64 @@ when isMainModule:
|
||||||
ys.sort(cmp[int])
|
ys.sort(cmp[int])
|
||||||
assert ys == @[1, 2, 7, 1056]
|
assert ys == @[1, 2, 7, 1056]
|
||||||
|
|
||||||
|
assert x == y
|
||||||
|
|
||||||
var z: IntSet
|
var z: IntSet
|
||||||
for i in 0..1000:
|
for i in 0..1000:
|
||||||
incl z, i
|
incl z, i
|
||||||
|
assert z.len() == i+1
|
||||||
for i in 0..1000:
|
for i in 0..1000:
|
||||||
assert i in z
|
assert z.contains(i)
|
||||||
|
|
||||||
|
var w = initIntSet()
|
||||||
|
w.incl(1)
|
||||||
|
w.incl(4)
|
||||||
|
w.incl(50)
|
||||||
|
w.incl(1001)
|
||||||
|
w.incl(1056)
|
||||||
|
|
||||||
|
var xuw = x.union(w)
|
||||||
|
var xuws = toSeq(items(xuw))
|
||||||
|
xuws.sort(cmp[int])
|
||||||
|
assert xuws == @[1, 2, 4, 7, 50, 1001, 1056]
|
||||||
|
|
||||||
|
var xiw = x.intersection(w)
|
||||||
|
var xiws = toSeq(items(xiw))
|
||||||
|
xiws.sort(cmp[int])
|
||||||
|
assert xiws == @[1, 1056]
|
||||||
|
|
||||||
|
var xdw = x.difference(w)
|
||||||
|
var xdws = toSeq(items(xdw))
|
||||||
|
xdws.sort(cmp[int])
|
||||||
|
assert xdws == @[2, 7]
|
||||||
|
|
||||||
|
var xsw = x.symmetricDifference(w)
|
||||||
|
var xsws = toSeq(items(xsw))
|
||||||
|
xsws.sort(cmp[int])
|
||||||
|
assert xsws == @[2, 4, 7, 50, 1001]
|
||||||
|
|
||||||
|
x.incl(w)
|
||||||
|
xs = toSeq(items(x))
|
||||||
|
xs.sort(cmp[int])
|
||||||
|
assert xs == @[1, 2, 4, 7, 50, 1001, 1056]
|
||||||
|
|
||||||
|
assert w <= x
|
||||||
|
|
||||||
|
assert w < x
|
||||||
|
|
||||||
|
assert(not disjoint(w, x))
|
||||||
|
|
||||||
|
var u = initIntSet()
|
||||||
|
u.incl(3)
|
||||||
|
u.incl(5)
|
||||||
|
u.incl(500)
|
||||||
|
assert disjoint(u, x)
|
||||||
|
|
||||||
|
var v = initIntSet()
|
||||||
|
v.incl(2)
|
||||||
|
v.incl(50)
|
||||||
|
|
||||||
|
x.excl(v)
|
||||||
|
xs = toSeq(items(x))
|
||||||
|
xs.sort(cmp[int])
|
||||||
|
assert xs == @[1, 4, 7, 1001, 1056]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue