[pypy-commit] pypy default: merge voidtype_strformat, which improves str formatting for record ndarrays

mattip noreply at buildbot.pypy.org
Sat Nov 23 20:34:26 CET 2013


Author: Matti Picus <matti.picus at gmail.com>
Branch: 
Changeset: r68295:f8f583791850
Date: 2013-11-23 21:33 +0200
http://bitbucket.org/pypy/pypy/changeset/f8f583791850/

Log:	merge voidtype_strformat, which improves str formatting for record
	ndarrays

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,3 +15,6 @@
 
 .. branch: armhf-singlefloat
 JIT support for singlefloats on ARM using the hardfloat ABI
+
+.. branch: voidtype_strformat
+Better support for record numpy arrays
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -249,12 +249,13 @@
             return space.wrap(self.dump_data())
         return space.call_function(cache.w_array_str, self)
 
-    def dump_data(self):
+    def dump_data(self, prefix='array(', suffix=')'):
         i = self.create_iter()
         first = True
         dtype = self.get_dtype()
         s = StringBuilder()
-        s.append('array([')
+        s.append(prefix)
+        s.append('[')
         while not i.done():
             if first:
                 first = False
@@ -262,7 +263,8 @@
                 s.append(', ')
             s.append(dtype.itemtype.str_format(i.getitem()))
             i.next()
-        s.append('])')
+        s.append(']')
+        s.append(suffix)
         return s.build()
 
     def create_iter(self, shape=None, backward_broadcast=False, require_index=False):
diff --git a/pypy/module/micronumpy/iter.py b/pypy/module/micronumpy/iter.py
--- a/pypy/module/micronumpy/iter.py
+++ b/pypy/module/micronumpy/iter.py
@@ -61,10 +61,22 @@
     def apply(self, space, orig_arr):
         arr = orig_arr.implementation
         ofs, subdtype = arr.dtype.fields[self.name]
-        # strides backstrides are identical, ofs only changes start
-        return W_NDimArray.new_slice(space, arr.start + ofs, arr.get_strides(),
-                                     arr.get_backstrides(),
-                                     arr.shape, arr, orig_arr, subdtype)
+        # ofs only changes start
+        # create a view of the original array by extending
+        # the shape, strides, backstrides of the array
+        from pypy.module.micronumpy.support import calc_strides
+        strides, backstrides = calc_strides(subdtype.shape,
+                                            subdtype.subdtype, arr.order)
+        final_shape = arr.shape + subdtype.shape
+        final_strides = arr.get_strides() + strides
+        final_backstrides = arr.get_backstrides() + backstrides
+        final_dtype = subdtype
+        print self.name,'strides',arr.get_strides(),strides
+        if subdtype.subdtype:
+            final_dtype = subdtype.subdtype
+        return W_NDimArray.new_slice(space, arr.start + ofs, final_strides,
+                                     final_backstrides,
+                                     final_shape, arr, orig_arr, final_dtype)
 
 class Chunks(BaseChunk):
     def __init__(self, l):
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
@@ -3096,7 +3096,9 @@
             ]
         h = np.array(buf, dtype=descr)
         assert len(h) == 2
-        skip('broken')  # XXX
+        assert h['x'].shape == (2, 2)
+        assert h['y'].strides == (41, 16, 8)
+        assert h['z'].shape == (2,)
         for v in (h, h[0], h['x']):
             repr(v)  # check for crash in repr
         assert (h['x'] == np.array([buf[0][0],
@@ -3127,6 +3129,22 @@
 
         assert len(list(a[0])) == 2
 
+    def test_3d_record(self):
+        from numpypy import dtype, array
+        dt = dtype([('name', 'S4'), ('x', float), ('y', float),
+                    ('block', int, (2, 2, 3))])
+        a = array([('aaaa', 1.0, 8.0, [[[1, 2, 3], [4, 5, 6]],
+                                       [[7, 8, 9], [10, 11, 12]]])],
+                  dtype=dt)
+        s = str(a)
+        i = a.item()
+        assert isinstance(i, tuple)
+        assert len(i) == 4
+        skip('incorrect formatting via dump_data')
+        assert s.endswith("[('aaaa', 1.0, 8.0, [[[1, 2, 3], [4, 5, 6]], "
+                          "[[7, 8, 9], [10, 11, 12]]])]")
+
+
     def test_issue_1589(self):
         import numpypy as numpy
         c = numpy.array([[(1, 2, 'a'), (3, 4, 'b')], [(5, 6, 'c'), (7, 8, 'd')]],
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
@@ -1789,6 +1789,40 @@
                                     dtype.subdtype)
         return W_NDimArray(implementation)
 
+    def read(self, arr, i, offset, dtype=None):
+        if dtype is None:
+            dtype = arr.dtype
+        return interp_boxes.W_VoidBox(arr, i + offset, dtype)
+
+    @jit.unroll_safe
+    def str_format(self, box):
+        assert isinstance(box, interp_boxes.W_VoidBox)
+        arr = self.readarray(box.arr, box.ofs, 0, box.dtype)
+        return arr.dump_data(prefix='', suffix='')
+
+    def to_builtin_type(self, space, item):
+        ''' From the documentation of ndarray.item():
+        "Void arrays return a buffer object for item(),
+         unless fields are defined, in which case a tuple is returned."
+        '''
+        assert isinstance(item, interp_boxes.W_VoidBox)
+        dt = item.arr.dtype
+        ret_unwrapped = []
+        for name in dt.fieldnames:
+            ofs, dtype = dt.fields[name]
+            if isinstance(dtype.itemtype, VoidType):
+                read_val = dtype.itemtype.readarray(item.arr, ofs, 0, dtype)
+            else:
+                read_val = dtype.itemtype.read(item.arr, ofs, 0, dtype)
+            if isinstance (read_val, interp_boxes.W_StringBox):
+                # StringType returns a str
+                read_val = space.wrap(dtype.itemtype.to_str(read_val))
+            ret_unwrapped = ret_unwrapped + [read_val,]
+        if len(ret_unwrapped) == 0:
+            raise OperationError(space.w_NotImplementedError, space.wrap(
+                    "item() for Void aray with no fields not implemented"))
+        return space.newtuple(ret_unwrapped)
+
 class RecordType(FlexibleType):
     T = lltype.Char
 
@@ -1848,7 +1882,8 @@
                 first = False
             else:
                 pieces.append(", ")
-            pieces.append(tp.str_format(tp.read(box.arr, box.ofs, ofs)))
+            val = tp.read(box.arr, box.ofs, ofs, subdtype)
+            pieces.append(tp.str_format(val))
         pieces.append(")")
         return "".join(pieces)
 


More information about the pypy-commit mailing list