def test_unpack(): for expected, size, bigendian, input in testcases: print "test_unpack:", expected, size, bigendian assert len(input) == size res = unpack_float(input, bigendian) if isnan(res) and isnan(expected): pass else: if size == 8: assert res == expected # exact result expected else: assert res == expected or abs(res - expected) < 1e-6
def push_primitive_constant(self, TYPE, value): ilasm = self.ilasm if TYPE is ootype.Void: pass elif TYPE is ootype.Bool: ilasm.opcode('ldc.i4', str(int(value))) elif TYPE is ootype.Char or TYPE is ootype.UniChar: ilasm.opcode('ldc.i4', ord(value)) elif TYPE is ootype.Float: if isinf(value): if value < 0.0: ilasm.opcode('ldc.r8', '(00 00 00 00 00 00 f0 ff)') else: ilasm.opcode('ldc.r8', '(00 00 00 00 00 00 f0 7f)') elif isnan(value): ilasm.opcode('ldc.r8', '(00 00 00 00 00 00 f8 ff)') else: ilasm.opcode('ldc.r8', repr(value)) elif isinstance(value, CDefinedIntSymbolic): ilasm.opcode('ldc.i4', DEFINED_INT_SYMBOLICS[value.expr]) elif TYPE in (ootype.Signed, ootype.Unsigned, rffi.SHORT): ilasm.opcode('ldc.i4', str(value)) elif TYPE in (ootype.SignedLongLong, ootype.UnsignedLongLong): ilasm.opcode('ldc.i8', str(value)) elif TYPE in (ootype.String, ootype.Unicode): if value._str is None: ilasm.opcode('ldnull') else: ilasm.opcode("ldstr", string_literal(value._str)) else: assert False, "Unexpected constant type"
def generic_initializationexpr(db, value, access_expr, decoration): if isinstance(typeOf(value), ContainerType): node = db.getcontainernode(value) lines = list(node.initializationexpr(decoration+'.')) lines[-1] += ',' return lines else: comma = ',' if typeOf(value) == Ptr(PyObject) and value: # cannot just write 'gxxx' as a constant in a structure :-( node = db.getcontainernode(value._obj) expr = 'NULL /*%s*/' % node.name node.where_to_copy_me.append('&%s' % access_expr) elif typeOf(value) == Float and (isinf(value) or isnan(value)): db.late_initializations.append(('%s' % access_expr, db.get(value))) expr = '0.0 /* patched later by %sinfinity */' % ( '-+'[value > 0]) else: expr = db.get(value) if typeOf(value) is Void: comma = '' expr += comma i = expr.find('\n') if i<0: i = len(expr) expr = '%s\t/* %s */%s' % (expr[:i], decoration, expr[i:]) return expr.split('\n')
def test_correct_tests(): import struct for number, size, bigendian, expected in testcases: if sys.version < (2, 5) and (isinf(number) or isnan(number)): continue # 'inf' and 'nan' unsupported in CPython 2.4's struct if bigendian: fmt = ">" else: fmt = "<" if size == 4: fmt += "f" else: fmt += "d" assert struct.pack(fmt, number) == expected res, = struct.unpack(fmt, expected) assert (isnan(res) and isnan(number)) or res == number or abs(res - number) < 1e-6
def name_float(value, db): if isinf(value): if value > 0: return '(Py_HUGE_VAL)' else: return '(-Py_HUGE_VAL)' elif isnan(value): return '(Py_HUGE_VAL/Py_HUGE_VAL)' else: return repr(value)
def pack_float(result, number, size, bigendian): """Append to 'result' the 'size' characters of the 32-bit or 64-bit IEEE representation of the number. """ if size == 4: bias = 127 exp = 8 prec = 23 else: bias = 1023 exp = 11 prec = 52 if isnan(number): sign = 0x80 man, e = 1.5, bias + 1 else: if number < 0: sign = 0x80 number *= -1 elif number == 0.0: for i in range(size): result.append('\x00') return else: sign = 0x00 if isinf(number): man, e = 1.0, bias + 1 else: man, e = math.frexp(number) if 0.5 <= man and man < 1.0: man *= 2 e -= 1 man -= 1 e += bias power_of_two = r_longlong(1) << prec mantissa = r_longlong(power_of_two * man + 0.5) if mantissa >> prec : mantissa = 0 e += 1 for i in range(size-2): result.append(chr(mantissa & 0xff)) mantissa >>= 8 x = (mantissa & ((1<<(15-exp))-1)) | ((e & ((1<<(exp-7))-1))<<(15-exp)) result.append(chr(x)) x = sign | e >> (exp - 7) result.append(chr(x)) if bigendian: first = len(result) - size last = len(result) - 1 for i in range(size // 2): (result[first + i], result[last - i]) = ( result[last - i], result[first + i])
def name_singlefloat(value, db): value = float(value) if isinf(value): if value > 0: return '((float)Py_HUGE_VAL)' else: return '((float)-Py_HUGE_VAL)' elif isnan(value): # XXX are these expressions ok? return '((float)(Py_HUGE_VAL/Py_HUGE_VAL))' else: return repr(value) + 'f'
def _push_double_constant(self, value): if isnan(value): jvm.DOUBLENAN.load(self) elif isinf(value): if value > 0: jvm.DOUBLEPOSINF.load(self) else: jvm.DOUBLENEGINF.load(self) elif value == 0.0: self.emit(jvm.DCONST_0) elif value == 1.0: self.emit(jvm.DCONST_1) else: # Big hack to avoid exponential notation: self.emit(jvm.LDC2, "%22.22f" % value)
def _hash_float(space, v): from pypy.objspace.std.longobject import hash__Long if isnan(v): return 0 # This is designed so that Python numbers of different types # that compare equal hash to the same value; otherwise comparisons # of mapping keys will turn out weird. fractpart, intpart = math.modf(v) if fractpart == 0.0: # This must return the same hash as an equal int or long. try: x = ovfcheck_float_to_int(intpart) # Fits in a C long == a Python int, so is its own hash. return x except OverflowError: # Convert to long and use its hash. try: w_lval = W_LongObject.fromfloat(v) except OverflowError: # can't convert to long int -- arbitrary if v < 0: return -271828 else: return 314159 return space.int_w(hash__Long(space, w_lval)) # The fractional part is non-zero, so we don't have to worry about # making this match the hash of some other type. # Use frexp to get at the bits in the double. # Since the VAX D double format has 56 mantissa bits, which is the # most of any double format in use, each of these parts may have as # many as (but no more than) 56 significant bits. # So, assuming sizeof(long) >= 4, each part can be broken into two # longs; frexp and multiplication are used to do that. # Also, since the Cray double format has 15 exponent bits, which is # the most of any double format in use, shifting the exponent field # left by 15 won't overflow a long (again assuming sizeof(long) >= 4). v, expo = math.frexp(v) v *= 2147483648.0 # 2**31 hipart = int(v) # take the top 32 bits v = (v - hipart) * 2147483648.0 # get the next 32 bits x = intmask(hipart + int(v) + (expo << 15)) return x
def format_float(self, w_value, char): space = self.space x = space.float_w(maybe_float(space, w_value)) if isnan(x): r = 'nan' elif isinf(x): r = 'inf' else: prec = self.prec if prec < 0: prec = 6 if char in 'fF' and x/1e25 > 1e25: char = chr(ord(char) + 1) # 'f' => 'g' try: r = formatd_overflow(self.f_alt, prec, char, x) except OverflowError: raise OperationError(space.w_OverflowError, space.wrap( "formatted float is too long (precision too large?)")) self.std_wp_number(r)
def repr_float(self, type_, value): from pypy.rlib.rarithmetic import isinf, isnan if isinf(value) or isnan(value): # Need hex repr import struct packed = struct.pack("d", value) if sys.byteorder == 'little': packed = packed[::-1] repr = "0x" + "".join([("%02x" % ord(ii)) for ii in packed]) else: repr = "%f" % value # llvm requires a . when using e notation if "e" in repr and "." not in repr: repr = repr.replace("e", ".0e") return repr
def repr_singlefloat(self, type_, value): from pypy.rlib.rarithmetic import isinf, isnan f = float(value) if isinf(f) or isnan(f): import struct packed = value._bytes if sys.byteorder == 'little': packed = packed[::-1] assert len(packed) == 4 repr = "0x" + "".join([("%02x" % ord(ii)) for ii in packed]) else: #repr = "%f" % f # XXX work around llvm2.1 bug, seems it doesnt like constants for floats repr = "fptrunc(double %f to float)" % f # llvm requires a . when using e notation if "e" in repr and "." not in repr: repr = repr.replace("e", ".0e") return repr
def _hash_float(f): """The algorithm behind compute_hash() for a float. This implementation is identical to the CPython implementation, except the fact that the integer case is not treated specially. In RPython, floats cannot be used with ints in dicts, anyway. """ from pypy.rlib.rarithmetic import intmask, isinf, isnan if isinf(f): if f < 0.0: return -271828 else: return 314159 elif isnan(f): return 0 v, expo = math.frexp(f) v *= TAKE_NEXT hipart = int(v) v = (v - float(hipart)) * TAKE_NEXT x = hipart + int(v) + (expo << 15) return intmask(x)
def format_float(self, w_value, char): space = self.space x = space.float_w(maybe_float(space, w_value)) if isnan(x): r = 'nan' elif isinf(x): if x < 0: r = '-inf' else: r = 'inf' else: prec = self.prec if prec < 0: prec = 6 if char in 'fF' and x / 1e25 > 1e25: char = chr(ord(char) + 1) # 'f' => 'g' try: r = formatd_overflow(self.f_alt, prec, char, x) except OverflowError: raise OperationError( space.w_OverflowError, space.wrap( "formatted float is too long (precision too large?)")) self.std_wp_number(r)
def test_primitive_log_n(): assert prim(primitives.FLOAT_LOG_N, [1.0]).value == 0.0 assert prim(primitives.FLOAT_LOG_N, [math.e]).value == 1.0 assert float_equals(prim(primitives.FLOAT_LOG_N, [10.0]), math.log(10)) assert isinf(prim(primitives.FLOAT_LOG_N, [0.0]).value) # works also for negative infinity assert isnan(prim(primitives.FLOAT_LOG_N, [-1.0]).value)