nimsets.nim 4.6 KB

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