nimsets.nim 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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 symbolic sets
  10. import
  11. ast, astalgo, lineinfos, bitsets, types, options
  12. proc inSet*(s: PNode, elem: PNode): bool =
  13. assert s.kind == nkCurly
  14. if s.kind != nkCurly:
  15. #internalError(s.info, "inSet")
  16. return false
  17. for i in 0..<s.len:
  18. if s[i].kind == nkRange:
  19. if leValue(s[i][0], elem) and
  20. leValue(elem, s[i][1]):
  21. return true
  22. else:
  23. if sameValue(s[i], elem):
  24. return true
  25. result = false
  26. proc overlap*(a, b: PNode): bool =
  27. if a.kind == nkRange:
  28. if b.kind == nkRange:
  29. # X..Y and C..D overlap iff (X <= D and C <= Y)
  30. result = leValue(a[0], b[1]) and
  31. leValue(b[0], a[1])
  32. else:
  33. result = leValue(a[0], b) and leValue(b, a[1])
  34. else:
  35. if b.kind == nkRange:
  36. result = leValue(b[0], a) and leValue(a, b[1])
  37. else:
  38. result = sameValue(a, b)
  39. proc someInSet*(s: PNode, a, b: PNode): bool =
  40. # checks if some element of a..b is in the set s
  41. assert s.kind == nkCurly
  42. if s.kind != nkCurly:
  43. #internalError(s.info, "SomeInSet")
  44. return false
  45. for i in 0..<s.len:
  46. if s[i].kind == nkRange:
  47. if leValue(s[i][0], b) and leValue(b, s[i][1]) or
  48. leValue(s[i][0], a) and leValue(a, s[i][1]):
  49. return true
  50. else:
  51. # a <= elem <= b
  52. if leValue(a, s[i]) and leValue(s[i], b):
  53. return true
  54. result = false
  55. proc toBitSet*(conf: ConfigRef; s: PNode): TBitSet =
  56. var first, j: Int128
  57. first = firstOrd(conf, s.typ[0])
  58. bitSetInit(result, int(getSize(conf, s.typ)))
  59. for i in 0..<s.len:
  60. if s[i].kind == nkRange:
  61. j = getOrdValue(s[i][0], first)
  62. while j <= getOrdValue(s[i][1], first):
  63. bitSetIncl(result, toInt64(j - first))
  64. inc(j)
  65. else:
  66. bitSetIncl(result, toInt64(getOrdValue(s[i]) - first))
  67. proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): PNode =
  68. var
  69. a, b, e, first: BiggestInt # a, b are interval borders
  70. elemType: PType
  71. n: PNode
  72. elemType = settype[0]
  73. first = firstOrd(conf, elemType).toInt64
  74. result = newNodeI(nkCurly, info)
  75. result.typ = settype
  76. result.info = info
  77. e = 0
  78. while e < s.len * ElemSize:
  79. if bitSetIn(s, e):
  80. a = e
  81. b = e
  82. while true:
  83. inc(b)
  84. if (b >= s.len * ElemSize) or not bitSetIn(s, b): break
  85. dec(b)
  86. let aa = newIntTypeNode(a + first, elemType)
  87. aa.info = info
  88. if a == b:
  89. result.add aa
  90. else:
  91. n = newNodeI(nkRange, info)
  92. n.typ = elemType
  93. n.add aa
  94. let bb = newIntTypeNode(b + first, elemType)
  95. bb.info = info
  96. n.add bb
  97. result.add n
  98. e = b
  99. inc(e)
  100. template nodeSetOp(a, b: PNode, op: untyped) {.dirty.} =
  101. var x = toBitSet(conf, a)
  102. let y = toBitSet(conf, b)
  103. op(x, y)
  104. result = toTreeSet(conf, x, a.typ, a.info)
  105. proc unionSets*(conf: ConfigRef; a, b: PNode): PNode = nodeSetOp(a, b, bitSetUnion)
  106. proc diffSets*(conf: ConfigRef; a, b: PNode): PNode = nodeSetOp(a, b, bitSetDiff)
  107. proc intersectSets*(conf: ConfigRef; a, b: PNode): PNode = nodeSetOp(a, b, bitSetIntersect)
  108. proc symdiffSets*(conf: ConfigRef; a, b: PNode): PNode = nodeSetOp(a, b, bitSetSymDiff)
  109. proc containsSets*(conf: ConfigRef; a, b: PNode): bool =
  110. let x = toBitSet(conf, a)
  111. let y = toBitSet(conf, b)
  112. result = bitSetContains(x, y)
  113. proc equalSets*(conf: ConfigRef; a, b: PNode): bool =
  114. let x = toBitSet(conf, a)
  115. let y = toBitSet(conf, b)
  116. result = bitSetEquals(x, y)
  117. proc complement*(conf: ConfigRef; a: PNode): PNode =
  118. var x = toBitSet(conf, a)
  119. for i in 0..high(x): x[i] = not x[i]
  120. result = toTreeSet(conf, x, a.typ, a.info)
  121. proc deduplicate*(conf: ConfigRef; a: PNode): PNode =
  122. let x = toBitSet(conf, a)
  123. result = toTreeSet(conf, x, a.typ, a.info)
  124. proc cardSet*(conf: ConfigRef; a: PNode): BiggestInt =
  125. let x = toBitSet(conf, a)
  126. result = bitSetCard(x)
  127. proc setHasRange*(s: PNode): bool =
  128. assert s.kind == nkCurly
  129. if s.kind != nkCurly:
  130. return false
  131. for i in 0..<s.len:
  132. if s[i].kind == nkRange:
  133. return true
  134. result = false
  135. proc emptyRange*(a, b: PNode): bool =
  136. result = not leValue(a, b) # a > b iff not (a <= b)