Esempio n. 1
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)
Esempio n. 2
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)
Esempio n. 3
0
def _(src, tgt, v):
  w = z3.fpToIEEEBV(v)
  i = z3.If(z3.Or(z3.fpIsZero(v), z3.fpIsSubnormal(v)),
    z3.BitVecVal(0,1),
    z3.BitVecVal(1,1))

  return z3.Concat(z3.Extract(78,63,w), i, z3.Extract(62,0,w))
Esempio n. 4
0
def _(src, tgt, v):
  w = z3.fpToIEEEBV(v)
  i = z3.If(z3.Or(z3.fpIsZero(v), z3.fpIsSubnormal(v)),
    z3.BitVecVal(0,1),
    z3.BitVecVal(1,1))

  return z3.Concat(z3.Extract(78,63,w), i, z3.Extract(62,0,w))
s = z3.Solver()

# C must be a power of 2, i.e. significand bits must all be 0.
s.add(z3.Extract(FLOAT_TY().sbits() - 1, 0, z3.fpToIEEEBV(c)) == 0)

for rm in [z3.RTZ(), z3.RNE()]:
    z3.set_default_rounding_mode(rm)
    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]))
s = z3.Solver()

# C must be a power of 2, i.e. significand bits must all be 0.
s.add(z3.Extract(FLOAT_TY().sbits() - 1, 0, z3.fpToIEEEBV(c)) == 0)

for rm in [z3.RTZ(), z3.RNE()]:
  z3.set_default_rounding_mode(rm)
  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]))