def verify_solution(ez, X_star,symbolTable,printModel=False): assert isinstance(symbolTable, collections.OrderedDict) assert isinstance(ez, z3.ExprRef) assert len(symbolTable)==X_star.size model=[] # (sympy.Symbol('x'), for (s,val) in zip(symbolTable.items(), X_star): var, sort = s[0],s[1] var=rename_var(var) # if ("!" in varr) or ("@" in var): # symVar="x_"+str(expr_z3.hash()) STOP HERE if sort == Sort.Float32: var_z3=z3.FP(str(var),z3.Float32()) val_z3=z3.FPVal(val,z3.Float32()) elif sort == Sort.Float64: var_z3=z3.FP(str(var),z3.Float64()) val_z3=z3.FPVal(val,z3.Float64()) else: raise NotImplementedError("Unexpected type %s" %sort) model.append((var_z3,val_z3)) if printModel: print "model: " print model ##Nice for debugging. #print "p"*90 #print z3.substitute(ez, *model) return _is_true(z3.simplify(z3.substitute(ez, *model)))
def get_z3_var(vartype, name, datatype_name=None, ctx=None): var = None if isinstance(vartype, z3.z3.DatatypeSortRef): # discrete values datatype var = z3.Const(name, vartype) elif vartype is Types.INT: var = z3.BitVec(name, 32, ctx=ctx) elif vartype is Types.INTEGER: var = z3.Int(name, ctx=ctx) elif vartype is Types.FLOAT: var = z3.FP(name, z3.Float32(), ctx=ctx) elif vartype is Types.REAL: var = z3.Real(name, ctx=ctx) elif vartype is Types.BOOL: var = z3.Bool(name, ctx=ctx) elif vartype is Types.STRING: var = z3.String(name, ctx=ctx) elif isinstance(vartype, list): datatype = _get_datatype_from_list(vartype, datatype_name) var = z3.Const(name, datatype) vartype = datatype else: raise ValueError( f"I do not know how to create a z3-variable for type {vartype} (name: {name})" ) assert var is not None, f"Var wasn't converted: vartype: {vartype}, name: {name}" var.type = vartype return var
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 get_z3_val(valtype, value, name, datatype_name=None, ctx=None): val = None if isinstance(valtype, z3.z3.DatatypeSortRef): # discrete values datatype val = getattr(valtype, value) elif valtype is Types.INT: try: val = z3.BitVecVal(value, 32, ctx=ctx) except Exception as exc: raise ValueError( f"Error during INT conversion. Cannot convert value: {value}, type: {type(value)}, name: {name}" ) elif valtype is Types.INTEGER: try: val = z3.IntVal(value, ctx=ctx) except Exception as exc: raise ValueError( f"Error during INTEGER conversion. Cannot convert value: {value}, type: {type(value)}, name: {name}" ) elif valtype is Types.FLOAT: try: val = z3.FPVal(value, z3.Float32(), ctx=ctx) except Exception as exc: raise ValueError( f"Error during FLOAT conversion. Cannot convert value: {value}, type: {type(value)}, name: {name}" ) elif valtype is Types.REAL: try: val = z3.RealVal(value, ctx=ctx) except Exception as exc: raise ValueError( f"Error during REAL conversion. Cannot convert value: {value}, type: {type(value)}, name: {name}" ) elif valtype is Types.BOOL: try: val = z3.BoolVal(value, ctx=ctx) except Exception as exc: raise ValueError( f"Error during BOOL conversion of value to INT. value: {value}, type: {type(value)}, name: {name}" ) elif valtype is Types.STRING: try: val = z3.StringVal(value, ctx=ctx) except Exception as exc: raise ValueError( f"Error during STRING conversion of value to INT. value: {value}, type: {type(value)}, name: {name}" ) elif isinstance(valtype, list): datatype = _get_datatype_from_list(valtype, datatype_name) val = getattr(datatype, value) valtype = datatype else: raise ValueError( f"I do not know how to create a z3-value for type {valtype}") assert val is not None, f"Value wasn't converted: valtype: {valtype}, value: {value}, name: {name}" val.type = valtype return val
def gen_symbolic_value(var_type, name): if var_type == bin_format.i32: return z3.BitVec(name, 32) if var_type == bin_format.i64: return z3.BitVec(name, 64) if var_type == bin_format.f32: return z3.FP(f'f32_{i}', z3.Float32()) if var_type == bin_format.f64: return z3.FP(name, z3.Float64()) raise TypeError('Unsupported variable type')
def fp_size_to_sort(size): size_class = z3.Float64() if size == 16: size_class = z3.Float16() elif size == 32: size_class = z3.Float32() elif size == 128: size_class = z3.Float128() return size_class
def _getSort(expr_z3): assert isinstance(expr_z3, z3.ExprRef) if expr_z3.sort() == z3.Float32(): return Sort.Float32 if expr_z3.sort() == z3.Float64(): return Sort.Float64 if expr_z3.sort() == z3.RealSort(): return Sort.Real if expr_z3.sort() == z3.IntSort(): return Sort.Int return Sort.UNKNOWN
def verify_solution(ez, X_star, symbolTable, printModel=False): assert isinstance(symbolTable, collections.OrderedDict) assert isinstance(ez, z3.ExprRef) assert isinstance(res, op.OptimizeResult) assert len(symbolTable) == X_star.size model = [] # (sympy.Symbol('x'), for (s, val) in zip(symbolTable.items(), X_star): var, sort = s[0], s[1] if sort == Sort.Float32: var_z3 = z3.FP(str(var), z3.Float32()) val_z3 = z3.FPVal(val, z3.Float32()) elif sort == Sort.Float64: var_z3 = z3.FP(str(var), z3.Float64()) val_z3 = z3.FPVal(val, z3.Float64()) else: raise NotImplementedError("Unexpected type %s" % sort) model.append((var_z3, val_z3)) if printModel: print "model: " print model return _is_true(z3.simplify(z3.substitute(ez, *model)))
def _ty_sort(ty): 'Translate a Type expression to a Z3 Sort' if isinstance(ty, IntType): return z3.BitVecSort(ty.width) return { PtrType: z3.BitVecSort(64), HalfType: z3.FloatHalf(), SingleType: z3.Float32(), DoubleType: z3.Float64(), FP128Type: z3.Float128(), X86FP80Type: z3.FPSort(15, 64), }[type(ty)]
def visit_float_is_positive(self, e): arg = e.arg(0) self._check_fp_sort(arg) arg_sort = e.arg(0).sort() zero = None # FIXME: This isn't sound. We can't distinguish +0 and -0 # in Coral's constraint language self._unsound_translation('fp.isPositive') 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.isPositive case') tmp = z3.fpGT(arg, zero) self.visit(tmp)
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 prepare_float(val, signext=False, size=SIZE) -> z3.FPRef: if z3.is_fp(val): return val size_class = z3.Float64() if size == 32: size_class = z3.Float32() elif size == 128: size_class = z3.Float128() if type(val) in (int, float): result = z3.FPVal(val) else: bv_val = prepare(val, signext, size) result = z3.fpBVToFP(bv_val, size_class) return result
def gen_symbolic_args(func: 'instance.FunctionInstance'): symbolic_params = [] for i, e in enumerate(func.functype.args): if e == bin_format.i32: symbolic_params.append(z3.BitVec(f'i32_bv_{i}', 32)) elif e == bin_format.i64: symbolic_params.append(z3.BitVec(f'i64_bv_{i}', 64)) elif e == bin_format.f32: # f32_bv = z3.BitVec(f'f32_bv_{i}', 32) # symbolic_params.append(z3.fpBVToFP(f32_bv, z3.Float32())) # another approach symbolic_params.append(z3.FP(f'f32_{i}', z3.Float32())) else: # f64_bv = z3.BitVec(f'f64_bv_{i}', 64) # symbolic_params.append(z3.fpBVToFP(f64_bv, z3.Float64())) # another approach symbolic_params.append(z3.FP(f'f64_{i}', z3.Float64())) return symbolic_params
def gen_symbolic_args(func: 'instance.FunctionInstance'): symbolic_params = list() for i, e in enumerate(func.functype.args): if e == bin_format.i32: symbolic_params.append(z3.BitVec(f'i32_bv_{i}', 32)) elif e == bin_format.i64: symbolic_params.append(z3.BitVec(f'i64_bv_{i}', 64)) elif e == bin_format.f32: # The first approach is bit-vector based # f32_bv = z3.BitVec(f'f32_bv_{i}', 32) # symbolic_params.append(z3.fpBVToFP(f32_bv, z3.Float32())) # The second approach is float-point based symbolic_params.append(z3.FP(f'f32_{i}', z3.Float32())) else: # The first approach is bit-vector based # f64_bv = z3.BitVec(f'f64_bv_{i}', 64) # symbolic_params.append(z3.fpBVToFP(f64_bv, z3.Float64())) # The second approach is float-point based symbolic_params.append(z3.FP(f'f64_{i}', z3.Float64())) return symbolic_params
def interp(tree, lookup, z3_mode): """Evaluate the arithmetic expression. Pass a tree as a Lark `Tree` object for the parsed expression. For `lookup`, provide a function for mapping variable names to values. """ op = tree.data if op in ('add', 'sub', 'mul', 'div', 'shl', 'shr'): # Binary operators. lhs = interp(tree.children[0], lookup, z3_mode) rhs = interp(tree.children[1], lookup, z3_mode) if op == 'add': return lhs + rhs elif op == 'sub': return lhs - rhs elif op == 'mul': return lhs * rhs elif op == 'div': return lhs / rhs elif op == 'shl': return lhs << rhs elif op == 'shr': return lhs >> rhs elif op == 'neg': # Negation. sub = interp(tree.children[0], lookup, z3_mode) return -sub elif op == 'int': # Literal number. if z3_mode: return z3.BitVecVal(int(tree.children[0]), 32) else: return int(tree.children[0]) elif op == 'float': # Literal number. if z3_mode: return z3.BitVecVal(float(tree.children[0]), 32) else: return float(tree.children[0]) elif op == 'var': # Variable lookup. return lookup(tree.children[0]) elif op == 'if': # Conditional. cond = interp(tree.children[0], lookup, z3_mode) true = interp(tree.children[1], lookup, z3_mode) false = interp(tree.children[2], lookup, z3_mode) return (cond != 0) * true + (cond == 0) * false elif op == "intcast": child = interp(tree.children[0], lookup, z3_mode) if z3_mode: return z3.BV2Int(child) else: return int(child) elif op == "floatcast": child = interp(tree.children[0], lookup, z3_mode) if z3_mode: return z3.fpBVToFP(child, z3.Float32()) else: return float(child) elif op == "int2bv": child = interp(tree.children[0], lookup, z3_mode) if z3_mode: return z3.Int2BV(child, 32) else: return child elif op == "float2bv": child = interp(tree.children[0], lookup, z3_mode) if z3_mode: return z3.fpToIEEEBV(child) else: return child
def _gen(expr_z3, symbolTable, cache, result): ###Leaf: var if _is_variable(expr_z3): if DEBUG: print "-- Branch _is_variable with ", expr_z3 symVar = expr_z3.decl().name() symVar = rename_var(symVar) if z3.is_int(expr_z3): symType = Sort.Int elif z3.is_fp(expr_z3): if expr_z3.sort() == z3.Float64(): symType = Sort.Float64 elif expr_z3.sort() == z3.Float32(): symType = Sort.Float32 else: raise NotImplementedError("Unexpected sort.", expr_z3.sort()) elif z3.is_real(expr_z3): symType = Sort.Float warnings.warn( "****WARNING****: Real variable '%s' treated as floating point" % symVar) else: raise NotImplementedError("Unexpected type for %s" % symbolName) if (symVar in symbolTable.keys()): assert symType == symbolTable[symVar] else: symbolTable[symVar] = symType if expr_z3.sort() == z3.Float32(): symVar = "TR32(%s)" % symVar # do the same ting for verify !!!!!!!! return symVar ###Leaf: val if _is_value(expr_z3): if DEBUG: print "-- Branch _is_value" if z3.is_fp(expr_z3) or z3.is_real(expr_z3): if DEBUG: print "---- Sub-Branch FP or Real" if isinstance(expr_z3, z3.FPNumRef): if DEBUG: print "------- Sub-Sub-Branch _is_FPNumRef" try: str_ret = str(sympy.Float(str(expr_z3), 17)) except ValueError: if expr_z3.isInf() and expr_z3.decl().kind( ) == z3.Z3_OP_FPA_PLUS_INF: str_ret = "INFINITY" elif expr_z3.isInf() and expr_z3.decl().kind( ) == z3.Z3_OP_FPA_MINUS_INF: str_ret = "- INFINITY" elif expr_z3.isNaN(): str_ret = "NAN" else: offset = 127 if expr_z3.sort() == z3.Float32( ) else 1023 #Z3 new version needs the offset to be taken into consideration expr_z3_exponent = expr_z3.exponent_as_long() - offset str_ret = str( sympy.Float((-1)**float(expr_z3.sign()) * float(str(expr_z3.significand())) * 2**(expr_z3_exponent), 17)) else: if DEBUG: print "------- Sub-Sub-Branch other than FPNumRef, probably FPRef" str_ret = str(sympy.Float(str((expr_z3)), 17)) elif z3.is_int(expr_z3): if DEBUG: print "---- Sub-Branch Integer" str_ret = str(sympy.Integer(str(expr_z3))) elif _is_true(expr_z3): str_ret = "0" elif _is_false(expr_z3): str_ret = "1" else: raise NotImplementedError( "[XSat: Coral Benchmarking] type not considered ") if expr_z3.sort() == z3.Float32(): str_ret = str_ret + "f" return str_ret #if (expr_z3 in cache): return cache[expr_z3] #cache will be a set of defined IDs #if (var_name(expr_z3) in cache): return cache[expr_z3] if (expr_z3.get_id() in cache): return var_name(expr_z3) cache.add(expr_z3.get_id()) #cache[expr_z3]=var_name(expr_z3) sort_z3 = expr_z3.decl().kind() expr_type = 'double' if expr_z3.sort() == z3.FPSort(8, 24): expr_type = 'float' ### if sort_z3 == z3.Z3_OP_FPA_LE: if DEBUG: print "-- Branch _is_le" lhs = _gen(expr_z3.arg(0), symbolTable, cache, result) rhs = _gen(expr_z3.arg(1), symbolTable, cache, result) toAppend= "double %s = DLE(%s,%s); " \ %( var_name(expr_z3), \ lhs,\ rhs,\ ) result.append(toAppend) return var_name(expr_z3) #########!!!!!!!!!!!! need to do something if sort_z3 == z3.Z3_OP_FPA_TO_FP: if DEBUG: print "-- Branch _is_fpFP" assert expr_z3.num_args() == 2 if not (_is_RNE(expr_z3.arg(0))): warnings.warn( "WARNING!!! I expect the first argument of fpFP is RNE, but it is ", expr_z3.arg(0)) x = _gen(expr_z3.arg(1), symbolTable, cache, result) if expr_z3.sort() == z3.FPSort(8, 24): x = "TR32(%s)" % x #else if expr_z3.sort()==z3.FPSort(8,24): # x = "TR(%s)" %x toAppend= "%s %s = %s; " \ %( expr_type, var_name(expr_z3), \ x,\ ) result.append(toAppend) return var_name(expr_z3) if sort_z3 == z3.Z3_OP_FPA_LT: if DEBUG: print "-- Branch _is_lt" lhs = _gen(expr_z3.arg(0), symbolTable, cache, result) rhs = _gen(expr_z3.arg(1), symbolTable, cache, result) toAppend= "double %s = DLT(%s,%s);" \ %( var_name(expr_z3), \ lhs,\ rhs,\ ) result.append(toAppend) return var_name(expr_z3) if _is_eq(expr_z3): if DEBUG: print "-- Branch _is_eq" lhs = _gen(expr_z3.arg(0), symbolTable, cache, result) rhs = _gen(expr_z3.arg(1), symbolTable, cache, result) toAppend= "double %s = DEQ(%s,%s);" \ %( var_name(expr_z3), \ lhs,\ rhs,\ ) result.append(toAppend) return var_name(expr_z3) if _is_fpMul(expr_z3): if DEBUG: print "-- Branch _is_fpMul" if not _is_RNE(expr_z3.arg(0)): warnings.warn( "WARNING!!! arg(0) is not RNE but is treated as RNE. arg(0) = ", expr_z3.arg(0)) assert expr_z3.num_args() == 3 lhs = _gen(expr_z3.arg(1), symbolTable, cache, result) rhs = _gen(expr_z3.arg(2), symbolTable, cache, result) toAppend= "%s %s = %s*%s; " \ %( expr_type, var_name(expr_z3), \ lhs,\ rhs,\ ) result.append(toAppend) return var_name(expr_z3) if _is_fpDiv(expr_z3): if DEBUG: print "-- Branch _is_fpDiv" if not _is_RNE(expr_z3.arg(0)): warnings.warn( "WARNING!!! arg(0) is not RNE but is treated as RNE. arg(0) = ", expr_z3.arg(0)) assert expr_z3.num_args() == 3 lhs = _gen(expr_z3.arg(1), symbolTable, cache, result) rhs = _gen(expr_z3.arg(2), symbolTable, cache, result) toAppend= "%s %s = %s/%s; " \ %(expr_type, var_name(expr_z3), \ lhs,\ rhs,\ ) result.append(toAppend) return var_name(expr_z3) if _is_fpAdd(expr_z3): if DEBUG: print "-- Branch _is_fpAdd" if not _is_RNE(expr_z3.arg(0)): warnings.warn( "WARNING!!! arg(0) is not RNE but is treated as RNE. arg(0) = ", expr_z3.arg(0)) assert expr_z3.num_args() == 3 lhs = _gen(expr_z3.arg(1), symbolTable, cache, result) rhs = _gen(expr_z3.arg(2), symbolTable, cache, result) toAppend= "%s %s = %s+%s;" \ %( expr_type, var_name(expr_z3), \ lhs,\ rhs,\ ) result.append(toAppend) return var_name(expr_z3) if z3.is_and(expr_z3): if DEBUG: print "-- Branch _is_and" ##TODO Not sure if symbolTable will be treated in a multi-threaded way toAppendExpr = _gen(expr_z3.arg(0), symbolTable, cache, result) for i in range(1, expr_z3.num_args()): toAppendExpr = 'BAND( %s,%s )' % ( toAppendExpr, _gen(expr_z3.arg(i), symbolTable, cache, result)) toAppend= "double %s = %s; " \ %( var_name(expr_z3), \ toAppendExpr,\ ) result.append(toAppend) return var_name(expr_z3) if z3.is_not(expr_z3): if DEBUG: print "-- Branch _is_not" assert expr_z3.num_args() == 1 if not (expr_z3.arg(0).num_args() == 2): warnings.warn( "WARNING!!! arg(0) is not RNE but is treated as RNE. arg(0) = ", expr_z3.arg(0)) op1 = _gen(expr_z3.arg(0).arg(0), symbolTable, cache, result) op2 = _gen(expr_z3.arg(0).arg(1), symbolTable, cache, result) if _is_ge(expr_z3.arg(0)): a = "DLT(%s,%s)" % (op1, op2) elif _is_gt(expr_z3.arg(0)): a = "DLE(%s,%s)" % (op1, op2) elif _is_le(expr_z3.arg(0)): a = "DGT(%s,%s)" % (op1, op2) elif _is_lt(expr_z3.arg(0)): a = "DGE(%s,%s)" % (op1, op2) elif _is_eq(expr_z3.arg(0)): a = "DNE(%s,%s)" % (op1, op2) elif _is_distinct(expr_z3.arg(0)): a = "DEQ(%s,%s)" % (op1, op2) else: raise NotImplementedError( "Not implemented case 004 for expr_z3 = %s. 'Not(or... )' is not handled yet" % expr_z3) toAppend= "%s %s = %s; " \ %( expr_type, var_name(expr_z3), \ a,\ ) result.append(toAppend) return var_name(expr_z3) if _is_fpNeg(expr_z3): if DEBUG: print "-- Branch _is_fpNeg" assert expr_z3.num_args() == 1 op1 = _gen(expr_z3.arg(0), symbolTable, cache, result) toAppend = "%s %s = - %s ;" \ %(expr_type, var_name(expr_z3), \ op1,\ ) result.append(toAppend) return var_name(expr_z3) raise NotImplementedError( "Not implemented case 002 for expr_z3 = %s, kind(%s)" % (expr_z3, expr_z3.decl().kind()))
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}!")
def f322i32(f: f32) -> i32: if utils.is_all_real(f): return struct.unpack('<i', struct.pack('<f', f))[0] return z3.fpToIEEEBV(f, z3.Float32())
def i322f32(i: i32) -> f32: if utils.is_all_real(i): i = int2i32(i) return struct.unpack('<f', struct.pack('<i', i))[0] return z3.fpToFP(i, z3.Float32())