Ejemplo n.º 1
0
def _fcmp(term, smt):
    x = smt.eval(term.x)
    y = smt.eval(term.y)

    if term.pred == '':
        var = z3.BitVec('fcmp_' + term.name, 4)
        ops = smt._fcmp_ops.itervalues()
        # since _fcmp_ops should never change, this should be stable

        cmp = ops.next()(x, y)
        i = 1
        for op in ops:
            cmp = z3.If(var == i, op(x, y), cmp)
            i += 1

    else:
        cmp = smt._fcmp_ops[term.pred](x, y)

    conds = []
    if 'nnan' in term.flags:
        conds += [z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y))]

    if 'ninf' in term.flags:
        conds += [z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y))]

    return smt._conditional_value(conds, bool_to_BitVec(cmp), term.name)
Ejemplo n.º 2
0
def _fcmp(term, smt):
  x = smt.eval(term.x)
  y = smt.eval(term.y)

  if term.pred == '':
    var = z3.BitVec('fcmp_' + term.name, 4)
    ops = smt._fcmp_ops.itervalues()
    # since _fcmp_ops should never change, this should be stable

    cmp = ops.next()(x,y)
    i = 1
    for op in ops:
      cmp = z3.If(var == i, op(x,y), cmp)
      i += 1

  else:
    cmp = smt._fcmp_ops[term.pred](x,y)

  conds = []
  if 'nnan' in term.flags:
    conds += [z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y))]

  if 'ninf' in term.flags:
    conds += [z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y))]

  return smt._conditional_value(
    conds,
    bool_to_BitVec(cmp),
    term.name)
Ejemplo n.º 3
0
  def _float_binary_operator(self, term, op):
    x = self.eval(term.x)
    y = self.eval(term.y)

    if 'nnan' in term.flags:
      self.add_defs(z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)),
        z3.Not(z3.fpIsNaN(op(x,y))))

    if 'ninf' in term.flags:
      self.add_defs(z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)),
        z3.Not(z3.fpIsInf(op(x,y))))

    if 'nsz' in term.flags:
      # NOTE: this will return a different qvar for each (in)direct reference
      # to this term. Is this desirable?
      nz = z3.fpMinusZero(_ty_sort(self.type(term)))
      self.add_defs(z3.Not(x == nz), z3.Not(y == nz))
      return op(x,y)  # turns -0 to +0

    return op(x,y)
Ejemplo n.º 4
0
    def _float_binary_operator(self, term, op):
        x = self.eval(term.x)
        y = self.eval(term.y)

        if 'nnan' in term.flags:
            self.add_defs(z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)),
                          z3.Not(z3.fpIsNaN(op(x, y))))

        if 'ninf' in term.flags:
            self.add_defs(z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)),
                          z3.Not(z3.fpIsInf(op(x, y))))

        if 'nsz' in term.flags:
            # NOTE: this will return a different qvar for each (in)direct reference
            # to this term. Is this desirable?
            nz = z3.fpMinusZero(_ty_sort(self.type(term)))
            self.add_defs(z3.Not(x == nz), z3.Not(y == nz))
            return op(x, y)  # turns -0 to +0

        return op(x, y)
Ejemplo n.º 5
0
  def _float_binary_operator(self, term, op):
    x = self.eval(term.x)
    y = self.eval(term.y)

    if 'nnan' in term.flags:
      self.add_defs(z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)),
        z3.Not(z3.fpIsNaN(op(x,y))))

    if 'ninf' in term.flags:
      self.add_defs(z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)),
        z3.Not(z3.fpIsInf(op(x,y))))

    if 'nsz' in term.flags:
      # NOTE: this will return a different qvar for each (in)direct reference
      # to this term. Is this desirable?
      q = self.fresh_var(self.type(term))
      self.add_qvar(q)  # FIXME
      self.add_defs(z3.fpEQ(q,0))
      z = op(x,y)
      return z3.If(z3.fpEQ(z,0), q, z)

    return op(x,y)
Ejemplo n.º 6
0
    def _float_binary_operator(self, term, op):
        x = self.eval(term.x)
        y = self.eval(term.y)

        if 'nnan' in term.flags:
            self.add_defs(z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)),
                          z3.Not(z3.fpIsNaN(op(x, y))))

        if 'ninf' in term.flags:
            self.add_defs(z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)),
                          z3.Not(z3.fpIsInf(op(x, y))))

        if 'nsz' in term.flags:
            # NOTE: this will return a different qvar for each (in)direct reference
            # to this term. Is this desirable?
            q = self.fresh_var(self.type(term))
            self.add_qvar(q)  # FIXME
            self.add_defs(z3.fpEQ(q, 0))
            z = op(x, y)
            return z3.If(z3.fpEQ(z, 0), q, z)

        return op(x, y)
Ejemplo n.º 7
0
    def _float_binary_operator(self, term, op):
        logger.debug('_fbo: %s\n%s', term, self.attrs[term])
        x = self.eval(term.x)
        y = self.eval(term.y)
        z = op(x, y)

        conds = []
        if 'nnan' in self.attrs[term]:
            df = z3.And(z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)),
                        z3.Not(z3.fpIsNaN(z)))
            conds.append(z3.Implies(self.attrs[term]['nnan'], df))

        elif 'nnan' in term.flags:
            conds += [
                z3.Not(z3.fpIsNaN(x)),
                z3.Not(z3.fpIsNaN(y)),
                z3.Not(z3.fpIsNaN(z))
            ]

        if 'ninf' in self.attrs[term]:
            df = z3.And(z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)),
                        z3.Not(z3.fpIsInf(z)))
            conds.append(z3.Implies(self.attrs[term]['ninf'], df))

        elif 'ninf' in term.flags:
            conds += [
                z3.Not(z3.fpIsInf(x)),
                z3.Not(z3.fpIsInf(y)),
                z3.Not(z3.fpIsInf(z))
            ]

        if 'nsz' in self.attrs[term] or 'nsz' in term.flags:
            # NOTE: this will return a different qvar for each (in)direct reference
            # to this term. Is this desirable?
            b = self.fresh_bool()
            self.add_qvar(b)
            z = op(x, y)

            c = z3.fpIsZero(z)
            if 'nsz' in self.attrs[term]:
                c = z3.And(self.attrs[term]['nsz'], c)

            s = _ty_sort(self.type(term))
            z = z3.If(c, z3.If(b, 0, z3.fpMinusZero(s)), z)

            if isinstance(term, FDivInst):
                c = [z3.Not(z3.fpIsZero(x)), z3.fpIsZero(y)]
                if 'nsz' in self.attrs[term]:
                    c.append(self.attrs[term]['nsz'])

                z = z3.If(
                    z3.And(c),
                    z3.If(b, z3.fpPlusInfinity(s), z3.fpMinusInfinity(s)), z)

        return self._conditional_value(conds, z, term.name)
Ejemplo n.º 8
0
  def _float_binary_operator(self, term, op):
    logger.debug('_fbo: %s\n%s', term, self.attrs[term])
    x = self.eval(term.x)
    y = self.eval(term.y)
    z = op(x,y)

    conds = []
    if 'nnan' in self.attrs[term]:
      df = z3.And(z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)),
        z3.Not(z3.fpIsNaN(z)))
      conds.append(z3.Implies(self.attrs[term]['nnan'], df))

    elif 'nnan' in term.flags:
      conds += [z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)),
        z3.Not(z3.fpIsNaN(z))]

    if 'ninf' in self.attrs[term]:
      df = z3.And(z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)),
        z3.Not(z3.fpIsInf(z)))
      conds.append(z3.Implies(self.attrs[term]['ninf'], df))

    elif 'ninf' in term.flags:
      conds += [z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)),
        z3.Not(z3.fpIsInf(z))]

    if 'nsz' in self.attrs[term] or 'nsz' in term.flags:
      # NOTE: this will return a different qvar for each (in)direct reference
      # to this term. Is this desirable?
      b = self.fresh_bool()
      self.add_qvar(b)
      z = op(x,y)

      c = z3.fpIsZero(z)
      if 'nsz' in self.attrs[term]:
        c = z3.And(self.attrs[term]['nsz'], c)

      s = _ty_sort(self.type(term))
      z = z3.If(c, z3.If(b, 0, z3.fpMinusZero(s)), z)

      if isinstance(term, FDivInst):
        c = [z3.Not(z3.fpIsZero(x)), z3.fpIsZero(y)]
        if 'nsz' in self.attrs[term]:
          c.append(self.attrs[term]['nsz'])

        z = z3.If(z3.And(c),
          z3.If(b, z3.fpPlusInfinity(s), z3.fpMinusInfinity(s)),
          z)

    return self._conditional_value(conds, z, term.name)
    before = a * c + b * c
    after = (a + b) * c

    # Check that before == after, allowing that 0 == -0.
    s.add(
        z3.Not(
            z3.Or(
                before == after,  #
                z3.And(z3.fpIsZero(before), z3.fpIsZero(after)))))

    for x in [
        (a * c),
        (b * c),
        (a + b),
    ]:
        s.add(z3.Not(z3.fpIsSubnormal(x)))
        s.add(z3.Not(z3.fpIsZero(x)))
        s.add(z3.Not(z3.fpIsInf(x)))

if s.check() == z3.sat:
    m = s.model()
    print("Counterexample found!")
    print(m)
    print("a*c:       ", z3.simplify(m[a] * m[c]))
    print("b*c:       ", z3.simplify(m[b] * m[c]))
    print("a+b:       ", z3.simplify(m[a] + m[b]))
    print("a*c + b*c: ", z3.simplify(m[a] * m[c] + m[b] * m[c]))
    print("(a+b) * c: ", z3.simplify((m[a] + m[b]) * m[c]))
else:
    print("Proved!")
  before = a * c + b * c
  after = (a + b) * c

  # Check that before == after, allowing that 0 == -0.
  s.add(
      z3.Not(
          z3.Or(
              before == after,  #
              z3.And(z3.fpIsZero(before), z3.fpIsZero(after)))))

  for x in [
      (a * c),
      (b * c),
      (a + b),
  ]:
    s.add(z3.Not(z3.fpIsSubnormal(x)))
    s.add(z3.Not(z3.fpIsZero(x)))
    s.add(z3.Not(z3.fpIsInf(x)))

if s.check() == z3.sat:
  m = s.model()
  print("Counterexample found!")
  print(m)
  print("a*c:       ", z3.simplify(m[a] * m[c]))
  print("b*c:       ", z3.simplify(m[b] * m[c]))
  print("a+b:       ", z3.simplify(m[a] + m[b]))
  print("a*c + b*c: ", z3.simplify(m[a] * m[c] + m[b] * m[c]))
  print("(a+b) * c: ", z3.simplify((m[a] + m[b]) * m[c]))
else:
  print("Proved!")