nimsets.nim 4.4 KB

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