summary refs log tree commit diff stats
path: root/tests/constraints
diff options
context:
space:
mode:
Diffstat (limited to 'tests/constraints')
0 files changed, 0 insertions, 0 deletions
4' href='#n54'>54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
#
#
#           The Nim Compiler
#        (c) Copyright 2012 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

# this unit handles Nim sets; it implements symbolic sets

import
  ast, astalgo, trees, nversion, msgs, platform, bitsets, types, renderer

proc inSet*(s: PNode, elem: PNode): bool =
  assert s.kind == nkCurly
  if s.kind != nkCurly:
    #internalError(s.info, "inSet")
    return false
  for i in countup(0, sonsLen(s) - 1):
    if s.sons[i].kind == nkRange:
      if leValue(s.sons[i].sons[0], elem) and
          leValue(elem, s.sons[i].sons[1]):
        return true
    else:
      if sameValue(s.sons[i], elem):
        return true
  result = false

proc overlap*(a, b: PNode): bool =
  if a.kind == nkRange:
    if b.kind == nkRange:
      # X..Y and C..D overlap iff (X <= D and C <= Y)
      result = leValue(a.sons[0], b.sons[1]) and
               leValue(b.sons[0], a.sons[1])
    else:
      result = leValue(a.sons[0], b) and leValue(b, a.sons[1])
  else:
    if b.kind == nkRange:
      result = leValue(b.sons[0], a) and leValue(a, b.sons[1])
    else:
      result = sameValue(a, b)

proc someInSet*(s: PNode, a, b: PNode): bool =
  # checks if some element of a..b is in the set s
  assert s.kind == nkCurly
  if s.kind != nkCurly:
    #internalError(s.info, "SomeInSet")
    return false
  for i in countup(0, sonsLen(s) - 1):
    if s.sons[i].kind == nkRange:
      if leValue(s.sons[i].sons[0], b) and leValue(b, s.sons[i].sons[1]) or
          leValue(s.sons[i].sons[0], a) and leValue(a, s.sons[i].sons[1]):
        return true
    else:
      # a <= elem <= b
      if leValue(a, s.sons[i]) and leValue(s.sons[i], b):
        return true
  result = false

proc toBitSet*(s: PNode, b: var TBitSet) =
  var first, j: BiggestInt
  first = firstOrd(s.typ.sons[0])
  bitSetInit(b, int(getSize(s.typ)))
  for i in countup(0, sonsLen(s) - 1):
    if s.sons[i].kind == nkRange:
      j = getOrdValue(s.sons[i].sons[0])
      while j <= getOrdValue(s.sons[i].sons[1]):
        bitSetIncl(b, j - first)
        inc(j)
    else:
      bitSetIncl(b, getOrdValue(s.sons[i]) - first)

proc toTreeSet*(s: TBitSet, settype: PType, info: TLineInfo): PNode =
  var
    a, b, e, first: BiggestInt # a, b are interval borders
    elemType: PType
    n: PNode
  elemType = settype.sons[0]
  first = firstOrd(elemType)
  result = newNodeI(nkCurly, info)
  result.typ = settype
  result.info = info
  e = 0
  while e < len(s) * ElemSize:
    if bitSetIn(s, e):
      a = e
      b = e
      while true:
        inc(b)
        if (b >= len(s) * ElemSize) or not bitSetIn(s, b): break
      dec(b)
      let aa = newIntTypeNode(nkIntLit, a + first, elemType)
      aa.info = info
      if a == b:
        addSon(result, aa)
      else:
        n = newNodeI(nkRange, info)
        n.typ = elemType
        addSon(n, aa)
        let bb = newIntTypeNode(nkIntLit, b + first, elemType)
        bb.info = info
        addSon(n, bb)
        addSon(result, n)
      e = b
    inc(e)

template nodeSetOp(a, b: PNode, op: untyped) {.dirty.} =
  var x, y: TBitSet
  toBitSet(a, x)
  toBitSet(b, y)
  op(x, y)
  result = toTreeSet(x, a.typ, a.info)

proc unionSets*(a, b: PNode): PNode = nodeSetOp(a, b, bitSetUnion)
proc diffSets*(a, b: PNode): PNode = nodeSetOp(a, b, bitSetDiff)
proc intersectSets*(a, b: PNode): PNode = nodeSetOp(a, b, bitSetIntersect)
proc symdiffSets*(a, b: PNode): PNode = nodeSetOp(a, b, bitSetSymDiff)

proc containsSets*(a, b: PNode): bool =
  var x, y: TBitSet
  toBitSet(a, x)
  toBitSet(b, y)
  result = bitSetContains(x, y)

proc equalSets*(a, b: PNode): bool =
  var x, y: TBitSet
  toBitSet(a, x)
  toBitSet(b, y)
  result = bitSetEquals(x, y)

proc complement*(a: PNode): PNode =
  var x: TBitSet
  toBitSet(a, x)
  for i in countup(0, high(x)): x[i] = not x[i]
  result = toTreeSet(x, a.typ, a.info)

proc deduplicate*(a: PNode): PNode =
  var x: TBitSet
  toBitSet(a, x)
  result = toTreeSet(x, a.typ, a.info)

proc cardSet*(a: PNode): BiggestInt =
  var x: TBitSet
  toBitSet(a, x)
  result = bitSetCard(x)

proc setHasRange*(s: PNode): bool =
  assert s.kind == nkCurly
  if s.kind != nkCurly:
    return false
  for i in countup(0, sonsLen(s) - 1):
    if s.sons[i].kind == nkRange:
      return true
  result = false

proc emptyRange*(a, b: PNode): bool =
  result = not leValue(a, b)  # a > b iff not (a <= b)