Пример #1
0
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
Пример #2
0
 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"
Пример #3
0
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')
Пример #4
0
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
Пример #5
0
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)
Пример #6
0
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])
Пример #7
0
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'
Пример #8
0
 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)
Пример #9
0
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
Пример #10
0
 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)
Пример #11
0
    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
Пример #12
0
 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
Пример #13
0
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)
Пример #14
0
 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)
Пример #15
0
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)