Author: Taavi Burns <taavi.bu...@gmail.com> Branch: numpy-ufuncs2 Changeset: r53485:9ecc8ac61ca0 Date: 2012-03-13 13:28 -0700 http://bitbucket.org/pypy/pypy/changeset/9ecc8ac61ca0/
Log: merge default diff --git a/pypy/annotation/builtin.py b/pypy/annotation/builtin.py --- a/pypy/annotation/builtin.py +++ b/pypy/annotation/builtin.py @@ -167,7 +167,7 @@ r.const = False return r - assert not issubclass(typ, (int,long)) or typ in (bool, int), ( + assert not issubclass(typ, (int, long)) or typ in (bool, int, long), ( "for integers only isinstance(.,int|r_uint) are supported") if s_obj.is_constant(): diff --git a/pypy/jit/backend/llsupport/test/test_descr.py b/pypy/jit/backend/llsupport/test/test_descr.py --- a/pypy/jit/backend/llsupport/test/test_descr.py +++ b/pypy/jit/backend/llsupport/test/test_descr.py @@ -148,7 +148,7 @@ # def get_alignment(code): # Retrieve default alignment for the compiler/platform - return struct.calcsize('l' + code) - struct.calcsize(code) + return struct.calcsize(lltype.SignedFmt + code) - struct.calcsize(code) assert descr1.basesize == get_alignment('c') assert descr2.basesize == get_alignment('p') assert descr3.basesize == get_alignment('p') diff --git a/pypy/jit/backend/llsupport/test/test_ffisupport.py b/pypy/jit/backend/llsupport/test/test_ffisupport.py --- a/pypy/jit/backend/llsupport/test/test_ffisupport.py +++ b/pypy/jit/backend/llsupport/test/test_ffisupport.py @@ -2,6 +2,7 @@ from pypy.jit.codewriter.longlong import is_64_bit from pypy.jit.backend.llsupport.descr import * from pypy.jit.backend.llsupport.ffisupport import * +from pypy.rlib.rarithmetic import is_emulated_long class FakeCPU: @@ -43,7 +44,7 @@ assert descr.result_flag == FLAG_UNSIGNED assert descr.is_result_signed() == False - if not is_64_bit: + if not is_64_bit or is_emulated_long: descr = get_call_descr_dynamic(FakeCPU(), [], types.slonglong, None, 42) assert descr is None # missing longlongs diff --git a/pypy/module/cpyext/test/test_stringobject.py b/pypy/module/cpyext/test/test_stringobject.py --- a/pypy/module/cpyext/test/test_stringobject.py +++ b/pypy/module/cpyext/test/test_stringobject.py @@ -105,6 +105,15 @@ )]) assert module.string_as_string("huheduwe") == "huhe" + def test_py_string_as_string_None(self): + module = self.import_extension('foo', [ + ("string_None", "METH_VARARGS", + ''' + return PyString_AsString(Py_None); + ''' + )]) + raises(TypeError, module.string_None) + def test_AsStringAndSize(self): module = self.import_extension('foo', [ ("getstring", "METH_NOARGS", diff --git a/pypy/module/math/test/test_direct.py b/pypy/module/math/test/test_direct.py --- a/pypy/module/math/test/test_direct.py +++ b/pypy/module/math/test/test_direct.py @@ -55,6 +55,12 @@ ('frexp', (-1.25,), lambda x: x == (-0.625, 1)), ('modf', (4.25,), lambda x: x == (0.25, 4.0)), ('modf', (-4.25,), lambda x: x == (-0.25, -4.0)), + ('copysign', (1.5, 0.0), 1.5), + ('copysign', (1.5, -0.0), -1.5), + ('copysign', (1.5, INFINITY), 1.5), + ('copysign', (1.5, -INFINITY), -1.5), + ('copysign', (1.5, NAN), 1.5), + ('copysign', (1.75, -NAN), -1.75), # special case for -NAN here ] OVFCASES = [ diff --git a/pypy/module/math/test/test_math.py b/pypy/module/math/test/test_math.py --- a/pypy/module/math/test/test_math.py +++ b/pypy/module/math/test/test_math.py @@ -1,3 +1,4 @@ +from __future__ import with_statement import sys from pypy.conftest import gettestobjspace from pypy.module.math.test import test_direct @@ -268,3 +269,7 @@ def __trunc__(self): return "truncated" assert math.trunc(foo()) == "truncated" + + def test_copysign_nan(self): + import math + assert math.copysign(1.0, float('-nan')) == -1.0 diff --git a/pypy/objspace/std/strutil.py b/pypy/objspace/std/strutil.py --- a/pypy/objspace/std/strutil.py +++ b/pypy/objspace/std/strutil.py @@ -177,8 +177,10 @@ return INFINITY elif low == "infinity" or low == "+infinity": return INFINITY - elif low == "nan" or low == "-nan" or low == "+nan": + elif low == "nan" or low == "+nan": return NAN + elif low == "-nan": + return -NAN try: return rstring_to_float(s) diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py --- a/pypy/rlib/rarithmetic.py +++ b/pypy/rlib/rarithmetic.py @@ -30,22 +30,54 @@ """ -import sys +import sys, struct from pypy.rpython import extregistry from pypy.rlib import objectmodel -# set up of machine internals -_bits = 0 -_itest = 1 -_Ltest = 1L -while _itest == _Ltest and type(_itest) is int: - _itest *= 2 - _Ltest *= 2 - _bits += 1 +""" +Long-term target: +We want to make pypy very flexible concerning its data type layout. +This is a larger task for later. -LONG_BIT = _bits+1 -LONG_MASK = _Ltest*2-1 -LONG_TEST = _Ltest +Short-term target: +We want to run PyPy on windows 64 bit. + +Problem: +On windows 64 bit, integers are only 32 bit. This is a problem for PyPy +right now, since it assumes that a c long can hold a pointer. +We therefore set up the target machine constants to obey this rule. +Right now this affects 64 bit Python only on windows. + +Note: We use the struct module, because the array module doesn's support +all typecodes. +""" + +def _get_bitsize(typecode): + return len(struct.pack(typecode, 1)) * 8 + +_long_typecode = 'l' +if _get_bitsize('P') > _get_bitsize('l'): + _long_typecode = 'P' + +def _get_long_bit(): + # whatever size a long has, make it big enough for a pointer. + return _get_bitsize(_long_typecode) + +# exported for now for testing array values. +# might go into its own module. +def get_long_pattern(x): + """get the bit pattern for a long, adjusted to pointer size""" + return struct.pack(_long_typecode, x) + +# used in tests for ctypes and for genc and friends +# to handle the win64 special case: +is_emulated_long = _long_typecode <> 'l' + +LONG_BIT = _get_long_bit() +LONG_MASK = (2**LONG_BIT)-1 +LONG_TEST = 2**(LONG_BIT-1) + +# XXX this is a good guess, but what if a long long is 128 bit? LONGLONG_BIT = 64 LONGLONG_MASK = (2**LONGLONG_BIT)-1 LONGLONG_TEST = 2**(LONGLONG_BIT-1) @@ -55,17 +87,23 @@ LONG_BIT_SHIFT += 1 assert LONG_BIT_SHIFT < 99, "LONG_BIT_SHIFT value not found?" +""" +int is no longer necessarily the same size as the target int. +We therefore can no longer use the int type as it is, but need +to use long everywhere. +""" + def intmask(n): - if isinstance(n, int): - return int(n) # possibly bool->int if isinstance(n, objectmodel.Symbolic): return n # assume Symbolics don't overflow assert not isinstance(n, float) + if is_valid_int(n): + return int(n) n = long(n) n &= LONG_MASK if n >= LONG_TEST: n -= 2*LONG_TEST - return int(n) + return n def longlongmask(n): assert isinstance(n, (int, long)) @@ -95,7 +133,12 @@ r_class.BITS == LONG_BIT and r_class.SIGNED) _should_widen_type._annspecialcase_ = 'specialize:memo' -del _bits, _itest, _Ltest +# the replacement for sys.maxint +maxint = int(LONG_TEST - 1) + +def is_valid_int(r): + return isinstance(r, (int, long)) and ( + -maxint - 1 <= r <= maxint) def ovfcheck(r): "NOT_RPYTHON" @@ -103,8 +146,10 @@ # raise OverflowError if the operation did overflow assert not isinstance(r, r_uint), "unexpected ovf check on unsigned" assert not isinstance(r, r_longlong), "ovfcheck not supported on r_longlong" - assert not isinstance(r,r_ulonglong),"ovfcheck not supported on r_ulonglong" - if type(r) is long: + assert not isinstance(r, r_ulonglong), "ovfcheck not supported on r_ulonglong" + if type(r) is long and not is_valid_int(r): + # checks only if applicable to r's type. + # this happens in the garbage collector. raise OverflowError, "signed integer expression did overflow" return r @@ -418,6 +463,9 @@ r_longlong = build_int('r_longlong', True, 64) r_ulonglong = build_int('r_ulonglong', False, 64) +r_long = build_int('r_long', True, 32) +r_ulong = build_int('r_ulong', False, 32) + longlongmax = r_longlong(LONGLONG_TEST - 1) if r_longlong is not r_int: @@ -425,6 +473,14 @@ else: r_int64 = int +# needed for ll_os_stat.time_t_to_FILE_TIME in the 64 bit case +if r_long is not r_int: + r_uint32 = r_ulong +else: + r_uint32 = r_uint + +# needed for ll_time.time_sleep_llimpl +maxint32 = int((1 << 31) -1) # the 'float' C type diff --git a/pypy/rlib/rfloat.py b/pypy/rlib/rfloat.py --- a/pypy/rlib/rfloat.py +++ b/pypy/rlib/rfloat.py @@ -295,7 +295,7 @@ return z INFINITY = 1e200 * 1e200 -NAN = INFINITY / INFINITY +NAN = abs(INFINITY / INFINITY) # bah, INF/INF gives us -NAN? try: # Try to get math functions added in 2.6. @@ -375,8 +375,7 @@ def log1p(x): "NOT_RPYTHON" - from pypy.rlib import rfloat - if abs(x) < rfloat.DBL_EPSILON // 2.: + if abs(x) < DBL_EPSILON // 2.: return x elif -.5 <= x <= 1.: y = 1. + x diff --git a/pypy/rpython/lltypesystem/lltype.py b/pypy/rpython/lltypesystem/lltype.py --- a/pypy/rpython/lltypesystem/lltype.py +++ b/pypy/rpython/lltypesystem/lltype.py @@ -7,7 +7,7 @@ from pypy.tool.identity_dict import identity_dict from pypy.tool import leakfinder from types import NoneType -from sys import maxint +from pypy.rlib.rarithmetic import maxint, is_valid_int, is_emulated_long import weakref class State(object): @@ -681,6 +681,11 @@ number = _numbertypes[type] = Number(name, type) return number +if is_emulated_long: + SignedFmt = 'q' +else: + SignedFmt = 'l' + Signed = build_number("Signed", int) Unsigned = build_number("Unsigned", r_uint) SignedLongLong = build_number("SignedLongLong", r_longlong) @@ -1654,7 +1659,7 @@ __slots__ = ('items',) def __init__(self, TYPE, n, initialization=None, parent=None, parentindex=None): - if not isinstance(n, int): + if not is_valid_int(n): raise TypeError, "array length must be an int" if n < 0: raise ValueError, "negative array length" diff --git a/pypy/translator/c/primitive.py b/pypy/translator/c/primitive.py --- a/pypy/translator/c/primitive.py +++ b/pypy/translator/c/primitive.py @@ -89,6 +89,12 @@ else: return '%dLL' % value +def is_positive_nan(value): + # bah. we don't have math.copysign() if we're running Python 2.5 + import struct + c = struct.pack("!d", value)[0] + return {'\x7f': True, '\xff': False}[c] + def name_float(value, db): if isinf(value): if value > 0: @@ -96,7 +102,10 @@ else: return '(-Py_HUGE_VAL)' elif isnan(value): - return '(Py_HUGE_VAL/Py_HUGE_VAL)' + if is_positive_nan(value): + return '(Py_HUGE_VAL/Py_HUGE_VAL)' + else: + return '(-(Py_HUGE_VAL/Py_HUGE_VAL))' else: x = repr(value) assert not x.startswith('n') @@ -112,7 +121,10 @@ return '((float)-Py_HUGE_VAL)' elif isnan(value): # XXX are these expressions ok? - return '((float)(Py_HUGE_VAL/Py_HUGE_VAL))' + if is_positive_nan(value): + return '((float)(Py_HUGE_VAL/Py_HUGE_VAL))' + else: + return '(-(float)(Py_HUGE_VAL/Py_HUGE_VAL))' else: return repr(value) + 'f' _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit