Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r58813:817f45e732ef Date: 2012-11-09 16:29 +0100 http://bitbucket.org/pypy/pypy/changeset/817f45e732ef/
Log: merge heads diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -15,6 +15,8 @@ See doc/cppyy.rst for full details and functionality. .. branch: nupypy-axis-arg-check Check that axis arg is valid in _numpypy +.. branch:less-gettestobjspace +.. branch: move-apptest-support .. branch: iterator-in-rpython .. branch: numpypy_count_nonzero @@ -42,6 +44,8 @@ Complex dtype support for numpy .. branch: numpypy-problems Improve dtypes intp, uintp, void, string and record +.. branch: numpypy.float16 +Add float16 numpy dtype .. branch: kill-someobject major cleanups including killing some object support .. branch: cpyext-PyThreadState_New diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py --- a/pypy/module/micronumpy/__init__.py +++ b/pypy/module/micronumpy/__init__.py @@ -55,6 +55,7 @@ 'inexact': 'interp_boxes.W_InexactBox', 'floating': 'interp_boxes.W_FloatingBox', 'float_': 'interp_boxes.W_Float64Box', + 'float16': 'interp_boxes.W_Float16Box', 'float32': 'interp_boxes.W_Float32Box', 'float64': 'interp_boxes.W_Float64Box', 'intp': 'types.IntP.BoxType', diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py --- a/pypy/module/micronumpy/interp_boxes.py +++ b/pypy/module/micronumpy/interp_boxes.py @@ -217,6 +217,9 @@ class W_FloatingBox(W_InexactBox): _attrs_ = () +class W_Float16Box(W_FloatingBox, PrimitiveBox): + descr__new__, _get_dtype = new_dtype_getter("float16") + class W_Float32Box(W_FloatingBox, PrimitiveBox): descr__new__, _get_dtype = new_dtype_getter("float32") @@ -458,6 +461,12 @@ __module__ = "numpypy", ) +W_Float16Box.typedef = TypeDef("float16", W_FloatingBox.typedef, + __module__ = "numpypy", + + __new__ = interp2app(W_Float16Box.descr__new__.im_func), +) + W_Float32Box.typedef = TypeDef("float32", W_FloatingBox.typedef, __module__ = "numpypy", diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py --- a/pypy/module/micronumpy/interp_dtype.py +++ b/pypy/module/micronumpy/interp_dtype.py @@ -465,6 +465,14 @@ #alternate_constructors=[space.w_buffer], # XXX no buffer in space ) + self.w_float16dtype = W_Dtype( + types.Float16(), + num=23, + kind=FLOATINGLTR, + name="float16", + char="e", + w_box_type=space.gettypefor(interp_boxes.W_Float16Box), + ) ptr_size = rffi.sizeof(rffi.CCHARP) if ptr_size == 4: intp_box = interp_boxes.W_Int32Box @@ -499,14 +507,14 @@ self.w_int16dtype, self.w_uint16dtype, self.w_int32dtype, self.w_uint32dtype, self.w_longdtype, self.w_ulongdtype, self.w_int64dtype, self.w_uint64dtype, - self.w_float32dtype, self.w_float64dtype, self.w_complex64dtype, + self.w_float16dtype, self.w_float32dtype, self.w_float64dtype, self.w_complex64dtype, self.w_complex128dtype, self.w_stringdtype, self.w_unicodedtype, self.w_voiddtype, self.w_intpdtype, self.w_uintpdtype, ] self.float_dtypes_by_num_bytes = sorted( (dtype.itemtype.get_element_size(), dtype) - for dtype in [self.w_float32dtype, self.w_float64dtype] + for dtype in [self.w_float16dtype, self.w_float32dtype, self.w_float64dtype] ) self.dtypes_by_name = {} # we reverse, so the stuff with lower numbers override stuff with diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py --- a/pypy/module/micronumpy/interp_ufuncs.py +++ b/pypy/module/micronumpy/interp_ufuncs.py @@ -407,7 +407,7 @@ dtypenum = dt2.num + 1 # UInt64 + signed = Float64 if dt2.num == 10: - dtypenum += 1 + dtypenum += 2 newdtype = interp_dtype.get_dtype_cache(space).builtin_dtypes[dtypenum] if (newdtype.itemtype.get_element_size() > dt2.itemtype.get_element_size() or @@ -419,7 +419,7 @@ if LONG_BIT == 32: dtypenum += 2 else: - dtypenum += 3 + dtypenum += 4 return interp_dtype.get_dtype_cache(space).builtin_dtypes[dtypenum] diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py --- a/pypy/module/micronumpy/test/test_base.py +++ b/pypy/module/micronumpy/test/test_base.py @@ -53,6 +53,7 @@ ulong_dtype = get_dtype_cache(space).w_ulongdtype int64_dtype = get_dtype_cache(space).w_int64dtype uint64_dtype = get_dtype_cache(space).w_uint64dtype + float16_dtype = get_dtype_cache(space).w_float16dtype float32_dtype = get_dtype_cache(space).w_float32dtype float64_dtype = get_dtype_cache(space).w_float64dtype @@ -73,9 +74,9 @@ # Coerce to floats, some of these will eventually be float16, or # whatever our smallest float type is. - assert find_unaryop_result_dtype(space, bool_dtype, promote_to_float=True) is float32_dtype # will be float16 if we ever put that in - assert find_unaryop_result_dtype(space, int8_dtype, promote_to_float=True) is float32_dtype # will be float16 if we ever put that in - assert find_unaryop_result_dtype(space, uint8_dtype, promote_to_float=True) is float32_dtype # will be float16 if we ever put that in + assert find_unaryop_result_dtype(space, bool_dtype, promote_to_float=True) is float16_dtype + assert find_unaryop_result_dtype(space, int8_dtype, promote_to_float=True) is float16_dtype + assert find_unaryop_result_dtype(space, uint8_dtype, promote_to_float=True) is float16_dtype assert find_unaryop_result_dtype(space, int16_dtype, promote_to_float=True) is float32_dtype assert find_unaryop_result_dtype(space, uint16_dtype, promote_to_float=True) is float32_dtype assert find_unaryop_result_dtype(space, int32_dtype, promote_to_float=True) is float64_dtype diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py --- a/pypy/module/micronumpy/test/test_dtypes.py +++ b/pypy/module/micronumpy/test/test_dtypes.py @@ -116,7 +116,7 @@ def test_bool_binop_types(self): from _numpypy import array, dtype types = [ - '?', 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'f', 'd' + '?', 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'f', 'd', 'e', ] a = array([True], '?') for t in types: @@ -142,7 +142,9 @@ tests.extend([('b','I','l'), ('b','L','d'), ('h','I','l'), ('h','L','d'), ('i','I','l'), ('i','L','d')]) for d1, d2, dout in tests: - assert (array([1], d1) + array([1], d2)).dtype is dtype(dout) + # make a failed test print helpful info + d3 = (array([1], d1) + array([1], d2)).dtype + assert (d1, d2, repr(d3)) == (d1, d2, repr(dtype(dout))) def test_add_int8(self): from _numpypy import array, dtype @@ -228,6 +230,7 @@ (numpy.int16, 5), (numpy.uint32, 7), (numpy.int64, 3), + (numpy.float16, 10.), (numpy.float32, 2.0), (numpy.float64, 4.32), ]: @@ -427,6 +430,17 @@ assert numpy.uint64(18446744073709551615) == 18446744073709551615 raises(OverflowError, numpy.uint64(18446744073709551616)) + def test_float16(self): + import _numpypy as numpy + assert numpy.float16.mro() == [numpy.float16, numpy.floating, + numpy.inexact, numpy.number, + numpy.generic, object] + + assert numpy.float16(12) == numpy.float64(12) + assert numpy.float16('23.4') == numpy.float16(23.4) + raises(ValueError, numpy.float16, '23.2df') + + def test_float32(self): import _numpypy as numpy diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -2038,6 +2038,7 @@ BaseNumpyAppTest.setup_class.im_func(cls) cls.w_data = cls.space.wrap(struct.pack('dddd', 1, 2, 3, 4)) cls.w_fdata = cls.space.wrap(struct.pack('f', 2.3)) + cls.w_float16val = cls.space.wrap('\x00E') # 5.0 in float16 cls.w_float32val = cls.space.wrap(struct.pack('f', 5.2)) cls.w_float64val = cls.space.wrap(struct.pack('d', 300.4)) cls.w_ulongval = cls.space.wrap(struct.pack('L', 12)) @@ -2109,8 +2110,7 @@ def test_fromstring_types(self): from _numpypy import (fromstring, int8, int16, int32, int64, uint8, - uint16, uint32, float32, float64) - + uint16, uint32, float16, float32, float64) a = fromstring('\xFF', dtype=int8) assert a[0] == -1 b = fromstring('\xFF', dtype=uint8) @@ -2131,6 +2131,8 @@ assert i[0] == float64(300.4) j = fromstring(self.ulongval, dtype='L') assert j[0] == 12 + k = fromstring(self.float16val, dtype=float16) + assert k[0] == float16(5.) def test_fromstring_invalid(self): from _numpypy import fromstring, uint16, uint8, int32 diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py --- a/pypy/module/micronumpy/types.py +++ b/pypy/module/micronumpy/types.py @@ -1,6 +1,5 @@ import functools import math -import struct from pypy.interpreter.error import OperationError from pypy.module.micronumpy import interp_boxes @@ -11,14 +10,15 @@ from pypy.rlib.rawstorage import (alloc_raw_storage, raw_storage_setitem, raw_storage_getitem) from pypy.rlib.objectmodel import specialize -from pypy.rlib.rarithmetic import widen, byteswap +from pypy.rlib.rarithmetic import widen, byteswap, r_ulonglong from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.rstruct.runpack import runpack +from pypy.rlib.rstruct.nativefmttable import native_is_bigendian +from pypy.rlib.rstruct.ieee import float_pack, float_unpack, unpack_float from pypy.tool.sourcetools import func_with_new_name from pypy.rlib import jit from pypy.rlib.rstring import StringBuilder - degToRad = math.pi / 180.0 log2 = math.log(2) log2e = 1. / log2 @@ -179,10 +179,8 @@ self._write(storage, i, offset, value) def runpack_str(self, s): - return self.box(runpack(self.format_code, s)) - - def pack_str(self, box): - return struct.pack(self.format_code, self.unbox(box)) + v = runpack(self.format_code, s) + return self.box(v) @simple_binary_op def add(self, v1, v2): @@ -298,9 +296,6 @@ value = byteswap(value) raw_storage_setitem(storage, i + offset, value) - def pack_str(self, box): - return struct.pack(self.format_code, byteswap(self.unbox(box))) - class Bool(BaseType, Primitive): _attrs_ = () @@ -914,10 +909,49 @@ #value = byteswap(value) XXX raw_storage_setitem(storage, i + offset, value) - def pack_str(self, box): - # XXX byteswap - return struct.pack(self.format_code, self.unbox(box)) +class Float16(BaseType, Float): + _attrs_ = () + _STORAGE_T = rffi.USHORT + T = rffi.DOUBLE + + BoxType = interp_boxes.W_Float16Box + + def get_element_size(self): + return rffi.sizeof(self._STORAGE_T) + + def runpack_str(self, s): + assert len(s) == 2 + fval = unpack_float(s, native_is_bigendian) + return self.box(fval) + + def for_computation(self, v): + return float(v) + + def default_fromstring(self, space): + return self.box(-1.0) + + def _read(self, storage, i, offset): + hbits = raw_storage_getitem(self._STORAGE_T, storage, i + offset) + return float_unpack(r_ulonglong(hbits), 2) + + def _write(self, storage, i, offset, value): + hbits = float_pack(value,2) + raw_storage_setitem(storage, i + offset, + rffi.cast(self._STORAGE_T, hbits)) + +class NonNativeFloat16(Float16): + _attrs_ = () + BoxType = interp_boxes.W_Float16Box + + def _read(self, storage, i, offset): + res = Float16._read(self, storage, i, offset) + #return byteswap(res) XXX + return res + + def _write(self, storage, i, offset, value): + #value = byteswap(value) XXX + Float16._write(self, storage, i, offset, value) class Float32(BaseType, Float): _attrs_ = () diff --git a/pypy/module/posix/app_posix.py b/pypy/module/posix/app_posix.py --- a/pypy/module/posix/app_posix.py +++ b/pypy/module/posix/app_posix.py @@ -311,6 +311,13 @@ self._stream.close() return self._proc.wait() or None # 0 => None __del__ = close + + def __enter__(self): + return self + + def __exit__(self, *k): + self.close() + def __getattr__(self, name): return getattr(self._stream, name) def __iter__(self): diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -501,6 +501,13 @@ assert res == '1\n' assert stream.close() is None + def test_popen_with(self): + os = self.posix + stream = os.popen('echo 1') + with stream as fp: + res = fp.read() + assert res == '1\n' + if hasattr(__import__(os.name), '_getfullpathname'): def test__getfullpathname(self): # nt specific diff --git a/pypy/rlib/rstruct/ieee.py b/pypy/rlib/rstruct/ieee.py --- a/pypy/rlib/rstruct/ieee.py +++ b/pypy/rlib/rstruct/ieee.py @@ -15,7 +15,7 @@ - return an int, not a float - do round-half-to-even, not round-half-away-from-zero. - We assume that x is finite and nonnegative; except wrong results + We assume that x is finite and nonnegative; expect wrong results if you use this for negative x. """ @@ -27,7 +27,7 @@ def float_unpack(Q, size): - """Convert a 32-bit or 64-bit integer created + """Convert a 16-bit, 32-bit or 64-bit integer created by float_pack into a Python float.""" if size == 8: @@ -40,6 +40,11 @@ MAX_EXP = 128 # FLT_MAX_EXP MANT_DIG = 24 # FLT_MANT_DIG BITS = 32 + elif size == 2: + MIN_EXP = -13 + MAX_EXP = 16 + MANT_DIG = 11 + BITS = 16 else: raise ValueError("invalid size value") @@ -83,6 +88,11 @@ MAX_EXP = 128 # FLT_MAX_EXP MANT_DIG = 24 # FLT_MANT_DIG BITS = 32 + elif size == 2: + MIN_EXP = -13 + MAX_EXP = 16 + MANT_DIG = 11 + BITS = 16 else: raise ValueError("invalid size value") diff --git a/pypy/rlib/rstruct/test/test_ieee.py b/pypy/rlib/rstruct/test/test_ieee.py --- a/pypy/rlib/rstruct/test/test_ieee.py +++ b/pypy/rlib/rstruct/test/test_ieee.py @@ -110,3 +110,35 @@ if isnan(x): continue self.check_float(x) + + def test_halffloat_exact(self): + #testcases generated from numpy.float16(x).view('uint16') + cases = [[0, 0], [10, 18688], [-10, 51456], [10e3, 28898], + [float('inf'), 31744], [-float('inf'), 64512]] + for c,h in cases: + hbit = float_pack(c, 2) + assert hbit == h + assert c == float_unpack(h, 2) + + def test_halffloat_inexact(self): + #testcases generated from numpy.float16(x).view('uint16') + cases = [[10.001, 18688, 10.], [-10.001, 51456, -10], + [0.027588, 10000, 0.027587890625], + [22001, 30047, 22000]] + for c,h,f in cases: + hbit = float_pack(c, 2) + assert hbit == h + assert f == float_unpack(h, 2) + + def test_halffloat_overunderflow(self): + import math + cases = [[670000, float('inf')], [-67000, -float('inf')], + [1e-08, 0], [-1e-8, -0.]] + for f1, f2 in cases: + try: + f_out = float_unpack(float_pack(f1, 2), 2) + except OverflowError: + f_out = math.copysign(float('inf'), f1) + assert f_out == f2 + assert math.copysign(1., f_out) == math.copysign(1., f2) + _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit