Commits

Armin Rigo committed 817f45e Merge

merge heads

Comments (0)

Files changed (15)

pypy/doc/whatsnew-head.rst

 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
 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

pypy/interpreter/argument.py

File contents unchanged.

pypy/interpreter/test/test_argument.py

File contents unchanged.

pypy/module/micronumpy/__init__.py

         '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',

pypy/module/micronumpy/interp_boxes.py

 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")
 
     __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",
 

pypy/module/micronumpy/interp_dtype.py

             #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
             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

pypy/module/micronumpy/interp_ufuncs.py

         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
         if LONG_BIT == 32:
             dtypenum += 2
         else:
-            dtypenum += 3
+            dtypenum += 4
         return interp_dtype.get_dtype_cache(space).builtin_dtypes[dtypenum]
 
 

pypy/module/micronumpy/test/test_base.py

         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
 
 
         # 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

pypy/module/micronumpy/test/test_dtypes.py

     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:
             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
             (numpy.int16, 5),
             (numpy.uint32, 7),
             (numpy.int64, 3),
+            (numpy.float16, 10.),
             (numpy.float32, 2.0),
             (numpy.float64, 4.32),
         ]:
         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
 

pypy/module/micronumpy/test/test_numarray.py

         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))
 
     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)
         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

pypy/module/micronumpy/types.py

 import functools
 import math
-import struct
 
 from pypy.interpreter.error import OperationError
 from pypy.module.micronumpy import interp_boxes
 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
             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):
         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_ = ()
 
         #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_ = ()

pypy/module/posix/app_posix.py

             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):

pypy/module/posix/test/test_posix2.py

             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

pypy/rlib/rstruct/ieee.py

       - 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.
 
     """
 
 
 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:
         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")
 
         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")
 

pypy/rlib/rstruct/test/test_ieee.py

             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)
+