summary refs log tree commit diff stats
path: root/compiler/bitsets.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/bitsets.nim')
-rw-r--r--compiler/bitsets.nim106
1 files changed, 66 insertions, 40 deletions
diff --git a/compiler/bitsets.nim b/compiler/bitsets.nim
index 5454ef5e7..7d142b01d 100644
--- a/compiler/bitsets.nim
+++ b/compiler/bitsets.nim
@@ -10,62 +10,88 @@
 # this unit handles Nim sets; it implements bit sets
 # the code here should be reused in the Nim standard library
 
+when defined(nimPreviewSlimSystem):
+  import std/assertions
+
 type
-  TBitSet* = seq[int8]        # we use byte here to avoid issues with
+  ElemType = byte
+  TBitSet* = seq[ElemType]    # we use byte here to avoid issues with
                               # cross-compiling; uint would be more efficient
                               # however
-
 const
-  ElemSize* = sizeof(int8) * 8
-
-proc bitSetInit*(b: var TBitSet, length: int)
-proc bitSetUnion*(x: var TBitSet, y: TBitSet)
-proc bitSetDiff*(x: var TBitSet, y: TBitSet)
-proc bitSetSymDiff*(x: var TBitSet, y: TBitSet)
-proc bitSetIntersect*(x: var TBitSet, y: TBitSet)
-proc bitSetIncl*(x: var TBitSet, elem: BiggestInt)
-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
-# implementation
-
-proc bitSetIn(x: TBitSet, e: BiggestInt): bool =
-  result = (x[int(e div ElemSize)] and toU8(int(1 shl (e mod ElemSize)))) !=
-      toU8(0)
-
-proc bitSetIncl(x: var TBitSet, elem: BiggestInt) =
+  ElemSize* = 8
+  One = ElemType(1)
+  Zero = ElemType(0)
+
+template modElemSize(arg: untyped): untyped = arg and 7
+template divElemSize(arg: untyped): untyped = arg shr 3
+
+proc bitSetIn*(x: TBitSet, e: BiggestInt): bool =
+  result = (x[int(e.divElemSize)] and (One shl e.modElemSize)) != Zero
+
+proc bitSetIncl*(x: var TBitSet, elem: BiggestInt) =
   assert(elem >= 0)
-  x[int(elem div ElemSize)] = x[int(elem div ElemSize)] or
-      toU8(int(1 shl (elem mod ElemSize)))
+  x[int(elem.divElemSize)] = x[int(elem.divElemSize)] or
+      (One shl elem.modElemSize)
 
-proc bitSetExcl(x: var TBitSet, elem: BiggestInt) =
-  x[int(elem div ElemSize)] = x[int(elem div ElemSize)] and
-      not toU8(int(1 shl (elem mod ElemSize)))
+proc bitSetExcl*(x: var TBitSet, elem: BiggestInt) =
+  x[int(elem.divElemSize)] = x[int(elem.divElemSize)] and
+      not(One shl elem.modElemSize)
 
-proc bitSetInit(b: var TBitSet, length: int) =
+proc bitSetInit*(b: var TBitSet, length: int) =
   newSeq(b, length)
 
-proc bitSetUnion(x: var TBitSet, y: TBitSet) =
-  for i in countup(0, high(x)): x[i] = x[i] or y[i]
+proc bitSetUnion*(x: var TBitSet, y: TBitSet) =
+  for i in 0..high(x): x[i] = x[i] or y[i]
 
-proc bitSetDiff(x: var TBitSet, y: TBitSet) =
-  for i in countup(0, high(x)): x[i] = x[i] and not y[i]
+proc bitSetDiff*(x: var TBitSet, y: TBitSet) =
+  for i in 0..high(x): x[i] = x[i] and not y[i]
 
-proc bitSetSymDiff(x: var TBitSet, y: TBitSet) =
-  for i in countup(0, high(x)): x[i] = x[i] xor y[i]
+proc bitSetSymDiff*(x: var TBitSet, y: TBitSet) =
+  for i in 0..high(x): x[i] = x[i] xor y[i]
 
-proc bitSetIntersect(x: var TBitSet, y: TBitSet) =
-  for i in countup(0, high(x)): x[i] = x[i] and y[i]
+proc bitSetIntersect*(x: var TBitSet, y: TBitSet) =
+  for i in 0..high(x): x[i] = x[i] and y[i]
 
-proc bitSetEquals(x, y: TBitSet): bool =
-  for i in countup(0, high(x)):
+proc bitSetEquals*(x, y: TBitSet): bool =
+  for i in 0..high(x):
     if x[i] != y[i]:
       return false
   result = true
 
-proc bitSetContains(x, y: TBitSet): bool =
-  for i in countup(0, high(x)):
-    if (x[i] and not y[i]) != int8(0):
+proc bitSetContains*(x, y: TBitSet): bool =
+  for i in 0..high(x):
+    if (x[i] and not y[i]) != Zero:
       return false
   result = true
+
+# Number of set bits for all values of int8
+const populationCount: array[uint8, uint8] = block:
+    var arr: array[uint8, uint8]
+
+    proc countSetBits(x: uint8): uint8 =
+      return
+        ( x and 0b00000001'u8) +
+        ((x and 0b00000010'u8) shr 1) +
+        ((x and 0b00000100'u8) shr 2) +
+        ((x and 0b00001000'u8) shr 3) +
+        ((x and 0b00010000'u8) shr 4) +
+        ((x and 0b00100000'u8) shr 5) +
+        ((x and 0b01000000'u8) shr 6) +
+        ((x and 0b10000000'u8) shr 7)
+
+
+    for it in low(uint8)..high(uint8):
+      arr[it] = countSetBits(cast[uint8](it))
+
+    arr
+
+proc bitSetCard*(x: TBitSet): BiggestInt =
+  result = 0
+  for it in x:
+    result.inc int(populationCount[it])
+
+proc bitSetToWord*(s: TBitSet; size: int): BiggestUInt =
+  result = 0
+  for j in 0..<size:
+    if j < s.len: result = result or (BiggestUInt(s[j]) shl (j * 8))