def parse_nan64(s: str): s = s.replace("_", "") f = float64(math.nan) if s[0] == '-': f = -f s = s[1:] elif s[0] == '+': s = s[1:] if s.startswith("nan:0x"): payload = int(s[6:], 16) bits = struct.unpack('>q', struct.pack('>d', f))[0] & 0xFFF7FFFFFFFFFFFE try: f = float64( struct.unpack('>d', struct.pack('>q', int64(bits | payload)))[0]) except struct.error: f = float64(math.nan) else: bits = struct.unpack('>q', struct.pack('>d', f))[0] & 0xFFFFFFFFFFFFFFFE try: f = float64(struct.unpack('>d', struct.pack('>q', int64(bits)))[0]) except struct.error: f = float64(math.nan) return f
def wrap_u64(vt, val): if vt == ValTypeI32: return int32(val) elif vt == ValTypeI64: return int64(val) elif vt == ValTypeF32: try: cov_val = struct.unpack('>f', struct.pack('>l', int64(val)))[0] except struct.error: cov_val = struct.unpack('>f', struct.pack('>L', int64(val)))[0] if math.isnan(cov_val): return float32(val) else: return float32(cov_val) elif vt == ValTypeF64: try: cov_val = struct.unpack('>d', struct.pack('>q', int64(val)))[0] except struct.error: cov_val = struct.unpack('>d', struct.pack('>Q', int64(val)))[0] if math.isnan(cov_val): return float64(val) else: return float64(cov_val) else: raise Exception("unreachable")
def test_nan(self): self.assertEqual(uint32(0x7fc00000), float32(str(math.nan))) self.assertEqual(uint32(0xffc00000), float32('-nan')) self.assertEqual(uint32(0x7f800000), float32(str(math.inf))) self.assertEqual(uint32(0xff800000), float32('-inf')) self.assertEqual(uint64(0x7ff8000000000001), float64(str(math.nan))) self.assertEqual(uint64(0xfff8000000000001), float64('-nan')) self.assertEqual(uint64(0x7ff0000000000000), float64(str(math.inf))) self.assertEqual(uint64(0xfff0000000000000), float64('-inf'))
def __trunc_sat_s(z, n): if math.isnan(z): return 0 min_value = -(int64(1) << (n - 1)) max_value = (int64(1) << (n - 1)) - 1 if z == -math.inf: return min_value if math.isinf(z): return max_value x = math.trunc(z) if x < float64(min_value): return min_value elif x >= float64(max_value): return max_value else: return int64(x)
def pop_f64(self): val = self.pop_numeric() try: val = struct.unpack('>d', struct.pack('>q', val))[0] except struct.error: val = struct.unpack('>d', struct.pack('>Q', val))[0] return float64(val)
def i32_trunc_f32u(vm, _): val = float64(vm.pop_f32()) if math.isinf(val): raise ErrIntOverflow if math.isnan(val): raise ErrConvertToInt f = math.trunc(val) if f > __MaxUint32 or f < 0: raise ErrIntOverflow vm.push_u32(uint32(f))
def visitExpected(self, ctx: WASTParser.ExpectedContext): if ctx.nan is not None: instr = new_instruction(ctx.op.text) opcode = instr.opcode if opcode == F32Const: instr.args = float32('nan') elif opcode == F64Const: instr.args = float64('nan') else: raise Exception("TODO:NAN") return instr return ctx.constInstr().accept(self)
def parse_float(s: str, bit_size): s = s.replace("_", "") if s.find("0x") >= 0 > s.find('P') and s.find('p') < 0: s += "p0" f = float.fromhex(s) elif s.find('P') > 0 or s.find('p') > 0: f = float.fromhex(s) else: f = 0.0 if float(s) == 0 else float(s) if bit_size == 32: return float32(f) else: return float64(f)
def __trunc_sat_u(z, n): if math.isnan(z): return 0 if z == -math.inf: return 0 max_value = (uint64(1) << n) - 1 if math.isinf(z): return max_value x = math.trunc(z) if x < 0: return 0 elif x >= float64(max_value): return max_value else: return uint64(x)
def get_consts(expr): if len(expr) == 0: vals = [] else: vals = [None] * len(expr) for i, instr in enumerate(expr): opcode = instr.opcode if opcode == I32Const: vals[i] = int32(instr.args) elif opcode == I64Const: vals[i] = int64(instr.args) elif opcode == F32Const: vals[i] = float32(instr.args) elif opcode == F64Const: vals[i] = float64(instr.args) else: raise Exception("TODO") return vals
def f64_promote_f32(vm, _): vm.push_f64(float64(vm.pop_f32()))
def f64_convert_i64u(vm, _): vm.push_f64(float64(vm.pop_u64()))
def f64_convert_i64s(vm, _): vm.push_f64(float64(vm.pop_s64()))
def f64_convert_i32u(vm, _): vm.push_f64(float64(vm.pop_u32()))
def f64_convert_i32s(vm, _): vm.push_f64(float64(vm.pop_s32()))
def f64_const(vm, args): vm.push_f64(float64(args))