def visit_float_is_infinite(self, e): arg = e.arg(0) self._check_fp_sort(arg) arg_sort = arg.sort() pos_inf = None neg_inf = None if self._is_float32_sort(arg_sort): pos_inf = z3.fpPlusInfinity(z3.Float32()) neg_inf = z3.fpMinusInfinity(z3.Float32()) elif self._is_float64_sort(arg_sort): pos_inf = z3.fpPlusInfinity(z3.Float64()) neg_inf = z3.fpMinusInfinity(z3.Float64()) else: raise CoralPrinterException('Unhandled fp.isInfinite op case') temp = z3.Or(z3.fpEQ(arg, pos_inf), z3.fpEQ(arg, neg_inf)) self.visit(temp)
def visit_eq(self, e): sort = e.arg(0).sort() if sort.kind() == z3.Z3_BOOL_SORT: self.sio.write('BNOT(BXOR(') self.visit(e.arg(0)) self.sio.write(',') self.visit(e.arg(1)) self.sio.write('))') elif sort.kind() == z3.Z3_BV_SORT: raise NotImplementedError('BitVector equal') self._check_bv_sort(e.arg(0)) self._check_bv_sort(e.arg(1)) elif sort.kind() == z3.Z3_FLOATING_POINT_SORT: self._check_fp_sort(e.arg(0)) # Either FEQ or both args are NaN # FIXME: This isn't quite right because +zero is != to -zero # but we have no way in Coral's constraint language of distinguishing # between them self._unsound_translation('=') new_expr = z3.Or( z3.And(z3.fpIsNaN(e.arg(0)), z3.fpIsNaN(e.arg(1))), z3.fpEQ(e.arg(0), e.arg(1))) self.visit(new_expr) else: raise CoralPrinterUnsupportedSort(sort)
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)
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)
def visit_float_is_zero(self, e): arg = e.arg(0) self._check_fp_sort(arg) arg_sort = arg.sort() zero = None # It doesn't matter if we pick +0 or -0 as we are using # the fp.eq operator which can't distinguish them, so # the choice of +0 is arbitrary. if self._is_float32_sort(arg_sort): zero = z3.fpPlusZero(z3.Float32()) elif self._is_float64_sort(arg_sort): zero = z3.fpPlusZero(z3.Float64()) else: raise CoralPrinterException('Unhandled fp.isZero op case') temp = z3.fpEQ(arg, zero) self.visit(temp)
def _op_raw_fpEQ(self, a, b): return z3.fpEQ(a, b, ctx=self._context)
def fpUEQ(x, y): return z3.Or(z3.fpEQ(x, y), z3.fpIsNaN(x), z3.fpIsNaN(y))
def fpUEQ(x, y): return z3.Or(z3.fpEQ(x,y), z3.fpIsNaN(x), z3.fpIsNaN(y))