예제 #1
0
 def _convert(self, obj):
     if isinstance(obj, FSort):
         return z3.FPSort(obj.exp, obj.mantissa, ctx=self._context)
     elif isinstance(obj, RM):
         if obj == RM_RNE:
             return z3.RNE(ctx=self._context)
         elif obj == RM_RNA:
             return z3.RNA(ctx=self._context)
         elif obj == RM_RTP:
             return z3.RTP(ctx=self._context)
         elif obj == RM_RTN:
             return z3.RTN(ctx=self._context)
         elif obj == RM_RTZ:
             return z3.RTZ(ctx=self._context)
         else:
             raise BackendError("unrecognized rounding mode")
     elif obj is True:
         return z3.BoolVal(True, ctx=self._context)
     elif obj is False:
         return z3.BoolVal(False, ctx=self._context)
     elif isinstance(obj, (numbers.Number, str)):
         return obj
     elif hasattr(obj, '__module__') and obj.__module__ in ('z3', 'z3.z3'):
         return obj
     else:
         l.debug("BackendZ3 encountered unexpected type %s", type(obj))
         raise BackendError("unexpected type %s encountered in BackendZ3" %
                            type(obj))
예제 #2
0
파일: backend_z3.py 프로젝트: avain/claripy
 def _convert(self, obj, result=None):
     if type(obj) is NativeBVV:
         return z3.BitVecVal(obj.value, obj.bits)
     elif isinstance(obj, FSort):
         return z3.FPSort(obj.exp, obj.mantissa)
     elif isinstance(obj, RM):
         if obj == RM_RNE:
             return z3.RNE()
         elif obj == RM_RNA:
             return z3.RNA()
         elif obj == RM_RTP:
             return z3.RTP()
         elif obj == RM_RTN:
             return z3.RTN()
         elif obj == RM_RTZ:
             return z3.RTZ()
         else:
             raise BackendError("unrecognized rounding mode")
     elif isinstance(obj, NativeFPV):
         val = str(obj.value)
         sort = self._convert(obj.sort)
         if val == 'inf':
             return z3.fpPlusInfinity(sort)
         elif val == '-inf':
             return z3.fpMinusInfinity(sort)
         elif val == '0.0':
             return z3.fpPlusZero(sort)
         elif val == '-0.0':
             return z3.fpMinusZero(sort)
         elif val == 'nan':
             return z3.fpNaN(sort)
         else:
             better_val = str(Decimal(obj.value))
             return z3.FPVal(better_val, sort)
     elif obj is True:
         return z3.BoolVal(True)
     elif obj is False:
         return z3.BoolVal(False)
     elif type(obj) in (int, long, float, str):
         return obj
     elif hasattr(obj, '__module__') and obj.__module__ == 'z3':
         return obj
     else:
         l.debug("BackendZ3 encountered unexpected type %s", type(obj))
         raise BackendError("unexpected type %s encountered in BackendZ3" %
                            type(obj))
# We do float16 because it lets the solver run much faster.  These results
# should generalize to fp32 and fp64, and you can verify this by changing the
# value of FLOAT_TY (and then waiting a while).
FLOAT_TY = z3.Float16

a = z3.FP("a", FLOAT_TY())
b = z3.FP("b", FLOAT_TY())
c = z3.FP("c", FLOAT_TY())

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),
예제 #4
0
    def cast(self, value, is_type, to_type):
        if is_type is Types.STRING and isinstance(to_type,
                                                  z3.z3.DatatypeSortRef):
            # the value is a string and it should be cast to a datatyperef
            # (i.e. an enum-type), just return the value because we can deal with it
            return value

        value_is_int = isinstance(value, int)
        value_is_float = isinstance(value, float)

        if is_type is to_type:  # already correct type, just return the value
            return value
            """ INT <---> INTEGER """
        elif is_type is Types.INT and to_type is Types.INTEGER:
            if value_is_int or value_is_float:
                return value  # this happens if it is an int numeral (e.g. 2)
            else:
                return z3.BV2Int(value)
        elif is_type is Types.INTEGER and to_type is Types.INT:
            if value_is_int or value_is_float:
                return value
            else:
                return z3.Int2BV(value, 32)
            """ INT <---> FLOAT """
        elif is_type is Types.FLOAT and to_type is Types.INT:
            if value_is_float:
                return value  # this happens if it is a float numeral (e.g. 3.14)
            else:
                return z3.fpToSBV(z3.RNE(), value, z3.BitVecSort(32))
        elif is_type is Types.INT and to_type is Types.FLOAT:
            if value_is_int:
                return value
            else:
                return z3.fpSignedToFP(z3.RNE(), value, z3.Float32())
            """ INTEGER <---> FLOAT """
        elif is_type is Types.FLOAT and to_type is Types.INTEGER:
            if value_is_float:
                return value  # this happens if it is a float numeral (e.g. 3.14)
            else:
                return self.cast(self.cast(value, Types.FLOAT, Types.INT),
                                 Types.INT, Types.INTEGER)
        elif is_type is Types.INTEGER and to_type is Types.FLOAT:
            if value_is_int:
                return value
            else:
                return self.cast(self.cast(value, Types.INTEGER, Types.INT),
                                 Types.INT, Types.FLOAT)
            """ from REAL """
        elif is_type is Types.REAL and to_type is Types.INTEGER:
            if value_is_float:
                return value
            else:
                return z3.ToInt(value)
        elif is_type is Types.REAL and to_type is Types.INT:
            return self.cast(self.cast(value, Types.REAL, Types.INTEGER),
                             Types.INTEGER, Types.INT)
        elif is_type is Types.REAL and to_type is Types.FLOAT:
            """
            Rounding modes: probably should make these parameterizable!
            roundNearestTiesToEven ... RNE() = default
            roundNearestTiesToAway ... RNA()
            roundTowardPositive ...... RTP()
            roundTowardNegative ...... RTN()
            roundTowardZero .......... RTZ()
            """
            if value_is_int or value_is_float:  # int numeral
                return value
            else:
                return z3.fpRealToFP(z3.RNE(), value, z3.Float32())
            """ to REAL """
        elif is_type is Types.INT and to_type is Types.REAL:
            if value_is_int or value_is_float:  # int numeral
                return value
            else:
                return z3.ToReal(self.cast(value, Types.INT, Types.INTEGER))
        elif is_type is Types.INTEGER and to_type is Types.REAL:
            if value_is_int or value_is_float:  # int numeral
                return value
            else:
                return z3.ToReal(value)
        elif is_type is Types.FLOAT and to_type is Types.REAL:
            if value_is_int or value_is_float:
                return value  # this happens if it is a float numeral (e.g. 3.14)
            else:
                return z3.fpToReal(value)
            """ FROM BOOL conversions """
        elif is_type is Types.BOOL and to_type is Types.INT:
            return z3.If(value, z3.BitVecVal(1, 32), z3.BitVecVal(0, 32))
        elif is_type is Types.BOOL and to_type is Types.INTEGER:
            return z3.If(value, 1, 0)
        elif is_type is Types.BOOL and to_type is Types.REAL:
            return z3.If(value, 1.0, 0.0)
        elif is_type is Types.BOOL and to_type is Types.FLOAT:
            return z3.If(value, z3.FPVal(1.0, z3.Float32()),
                         z3.FPVal(0.0, z3.Float32()))
            """ TO BOOL conversions """
        elif is_type is Types.INT and to_type is Types.BOOL:
            return value == 1
        elif is_type is Types.INTEGER and to_type is Types.BOOL:
            return value == 1
        elif is_type is Types.REAL and to_type is Types.BOOL:
            return value == 1
        elif is_type is Types.FLOAT and to_type is Types.BOOL:
            return value == 1

        raise TypeError(f"Don't know how to cast from {is_type} to {to_type}!")
예제 #5
0
def _(term, smt):
    v = smt.eval(term._args[0])
    return z3.fpToFP(z3.RNE(), v, _ty_sort(smt.type(term)))