bitsets.nim 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2012 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # this unit handles Nim sets; it implements bit sets
  10. # the code here should be reused in the Nim standard library
  11. when defined(nimPreviewSlimSystem):
  12. import std/assertions
  13. type
  14. ElemType = byte
  15. TBitSet* = seq[ElemType] # we use byte here to avoid issues with
  16. # cross-compiling; uint would be more efficient
  17. # however
  18. const
  19. ElemSize* = 8
  20. One = ElemType(1)
  21. Zero = ElemType(0)
  22. template modElemSize(arg: untyped): untyped = arg and 7
  23. template divElemSize(arg: untyped): untyped = arg shr 3
  24. proc bitSetIn*(x: TBitSet, e: BiggestInt): bool =
  25. result = (x[int(e.divElemSize)] and (One shl e.modElemSize)) != Zero
  26. proc bitSetIncl*(x: var TBitSet, elem: BiggestInt) =
  27. assert(elem >= 0)
  28. x[int(elem.divElemSize)] = x[int(elem.divElemSize)] or
  29. (One shl elem.modElemSize)
  30. proc bitSetExcl*(x: var TBitSet, elem: BiggestInt) =
  31. x[int(elem.divElemSize)] = x[int(elem.divElemSize)] and
  32. not(One shl elem.modElemSize)
  33. proc bitSetInit*(b: var TBitSet, length: int) =
  34. newSeq(b, length)
  35. proc bitSetUnion*(x: var TBitSet, y: TBitSet) =
  36. for i in 0..high(x): x[i] = x[i] or y[i]
  37. proc bitSetDiff*(x: var TBitSet, y: TBitSet) =
  38. for i in 0..high(x): x[i] = x[i] and not y[i]
  39. proc bitSetSymDiff*(x: var TBitSet, y: TBitSet) =
  40. for i in 0..high(x): x[i] = x[i] xor y[i]
  41. proc bitSetIntersect*(x: var TBitSet, y: TBitSet) =
  42. for i in 0..high(x): x[i] = x[i] and y[i]
  43. proc bitSetEquals*(x, y: TBitSet): bool =
  44. for i in 0..high(x):
  45. if x[i] != y[i]:
  46. return false
  47. result = true
  48. proc bitSetContains*(x, y: TBitSet): bool =
  49. for i in 0..high(x):
  50. if (x[i] and not y[i]) != Zero:
  51. return false
  52. result = true
  53. # Number of set bits for all values of int8
  54. const populationCount: array[uint8, uint8] = block:
  55. var arr: array[uint8, uint8]
  56. proc countSetBits(x: uint8): uint8 =
  57. return
  58. ( x and 0b00000001'u8) +
  59. ((x and 0b00000010'u8) shr 1) +
  60. ((x and 0b00000100'u8) shr 2) +
  61. ((x and 0b00001000'u8) shr 3) +
  62. ((x and 0b00010000'u8) shr 4) +
  63. ((x and 0b00100000'u8) shr 5) +
  64. ((x and 0b01000000'u8) shr 6) +
  65. ((x and 0b10000000'u8) shr 7)
  66. for it in low(uint8)..high(uint8):
  67. arr[it] = countSetBits(cast[uint8](it))
  68. arr
  69. proc bitSetCard*(x: TBitSet): BiggestInt =
  70. result = 0
  71. for it in x:
  72. result.inc int(populationCount[it])
  73. proc bitSetToWord*(s: TBitSet; size: int): BiggestUInt =
  74. result = 0
  75. for j in 0..<size:
  76. if j < s.len: result = result or (BiggestUInt(s[j]) shl (j * 8))