diff --git a/compiler/bitsets.nim b/compiler/bitsets.nim index 5454ef5e70dd..6afd1bd78071 100644 --- a/compiler/bitsets.nim +++ b/compiler/bitsets.nim @@ -28,6 +28,7 @@ proc bitSetExcl*(x: var TBitSet, elem: BiggestInt) proc bitSetIn*(x: TBitSet, e: BiggestInt): bool proc bitSetEquals*(x, y: TBitSet): bool proc bitSetContains*(x, y: TBitSet): bool +proc bitSetCard*(x: TBitSet): BiggestInt # implementation proc bitSetIn(x: TBitSet, e: BiggestInt): bool = @@ -69,3 +70,27 @@ proc bitSetContains(x, y: TBitSet): bool = if (x[i] and not y[i]) != int8(0): return false result = true + +# Number of set bits for all values of int8 +const populationCount: array[low(int8)..high(int8), int8] = [ + 1.int8, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7 +] + +proc bitSetCard(x: TBitSet): BiggestInt = + for it in x: + result.inc populationCount[it] diff --git a/compiler/nimsets.nim b/compiler/nimsets.nim index bda753e85f16..8ec4d3c0dd5c 100644 --- a/compiler/nimsets.nim +++ b/compiler/nimsets.nim @@ -27,7 +27,7 @@ proc intersectSets*(a, b: PNode): PNode proc symdiffSets*(a, b: PNode): PNode proc containsSets*(a, b: PNode): bool proc equalSets*(a, b: PNode): bool -proc cardSet*(s: PNode): BiggestInt +proc cardSet*(a: PNode): BiggestInt # implementation proc inSet(s: PNode, elem: PNode): bool = @@ -156,16 +156,10 @@ proc deduplicate*(a: PNode): PNode = toBitSet(a, x) result = toTreeSet(x, a.typ, a.info) -proc cardSet(s: PNode): BiggestInt = - # here we can do better than converting it into a compact set - # we just count the elements directly - result = 0 - for i in countup(0, sonsLen(s) - 1): - if s.sons[i].kind == nkRange: - result = result + getOrdValue(s.sons[i].sons[1]) - - getOrdValue(s.sons[i].sons[0]) + 1 - else: - inc(result) +proc cardSet(a: PNode): BiggestInt = + var x: TBitSet + toBitSet(a, x) + result = bitSetCard(x) proc setHasRange(s: PNode): bool = if s.kind != nkCurly: diff --git a/tests/sets/tsets.nim b/tests/sets/tsets.nim index 53a955af8cbd..96d5debc79b7 100644 --- a/tests/sets/tsets.nim +++ b/tests/sets/tsets.nim @@ -202,3 +202,7 @@ var #import compiler.msgs echo warnUninit in gNotes + +# 7555 +doAssert {-1.int8, -2, -2}.card == 2 +doAssert {1, 2, 2, 3..5, 4..6}.card == 6 \ No newline at end of file