Author: mattip <matti.pi...@gmail.com>
Branch: dtypes-compatability
Changeset: r78232:90f488ee3b1d
Date: 2015-06-21 22:31 +0300
http://bitbucket.org/pypy/pypy/changeset/90f488ee3b1d/

Log:    wip - fixing align

diff --git a/pypy/module/micronumpy/descriptor.py 
b/pypy/module/micronumpy/descriptor.py
--- a/pypy/module/micronumpy/descriptor.py
+++ b/pypy/module/micronumpy/descriptor.py
@@ -561,17 +561,20 @@
 
 
 @specialize.arg(2)
-def dtype_from_list(space, w_lst, simple, align=False):
+def dtype_from_list(space, w_lst, simple, align=False, offsets=None):
     lst_w = space.listview(w_lst)
     fields = {}
-    offset = 0
+    if offsets is None:
+        offsets = [0] * len(lst_w)
     names = []
     maxalign = 0
+    total = 0
     for i in range(len(lst_w)):
         w_elem = lst_w[i]
         title = None
         if simple:
-            subdtype = descr__new__(space, space.gettypefor(W_Dtype), w_elem)
+            subdtype = descr__new__(space, space.gettypefor(W_Dtype), w_elem,
+                                    align=align)
             fldname = 'f%d' % i
         else:
             w_shape = space.newtuple([])
@@ -581,7 +584,8 @@
                     w_shape = space.newtuple([w_shape])
             else:
                 w_fldname, w_flddesc = space.fixedview(w_elem, 2)
-            subdtype = descr__new__(space, space.gettypefor(W_Dtype), 
w_flddesc, w_shape=w_shape)
+            subdtype = descr__new__(space, space.gettypefor(W_Dtype),
+                                    w_flddesc, w_shape=w_shape, align=align)
             if space.isinstance_w(w_fldname, space.w_tuple):
                 fldlist = space.listview(w_fldname)
                 fldname = space.str_w(fldlist[0])
@@ -597,17 +601,27 @@
             if fldname in fields:
                 raise oefmt(space.w_ValueError, "two fields with the same 
name")
         assert isinstance(subdtype, W_Dtype)
-        fields[fldname] = offset, subdtype
+        fields[fldname] = offsets[i], subdtype
         if title is not None:
-            fields[title] = offset, subdtype
-        offset += subdtype.elsize
+            fields[title] = offsets[i], subdtype
         maxalign = max(subdtype.elsize, maxalign)
+        if  i + 1 < len(offsets) and offsets[i + 1] == 0:
+            delta = subdtype.elsize
+            if align:
+                # Set offset to the next power-of-two above delta
+                delta = (delta + maxalign -1) & (-maxalign)
+                if delta > offsets[i]:
+                    for j in range(i):
+                        offsets[j+1] = delta + offsets[j]
+            offsets[i + 1] = offsets[i] + delta
+            print maxalign, delta, subdtype, subdtype.elsize
+        if align:
+            total = len(offsets) * maxalign
+        else:
+            total += subdtype.elsize
         names.append((fldname, title))
-    if align:
-        # Set offset to the next power-of-two above offset
-        offset = (offset + maxalign -1) & (-maxalign)
     retval = W_Dtype(types.RecordType(space), 
space.gettypefor(boxes.W_VoidBox),
-                   names=names, fields=fields, elsize=offset)
+                   names=names, fields=fields, elsize=total)
     retval.flags |= NPY.NEEDS_PYAPI
     return retval
 
@@ -628,6 +642,28 @@
         return None
     return space.listview(w_val)
 
+def _usefields(space, w_dict, align):
+    # Only for testing, a shortened version of the real _usefields
+    allfields = []
+    for fname in w_dict.iterkeys().iterator:
+        obj = _get_list_or_none(space, w_dict, fname)
+        num = space.int_w(obj[1])
+        format = dtype_from_spec(space, obj[0], align=align)
+        if len(obj) > 2:
+            title = obj[2]
+        else:
+            title = None
+        allfields.append((fname, format, num, title))
+    allfields.sort(key=lambda x: x[2])
+    names   = [x[0] for x in allfields]
+    formats = [x[1] for x in allfields]
+    offsets = [x[2] for x in allfields]
+    titles  = [x[3] for x in allfields]
+    aslist = []
+    for i in range(len(names)):
+        aslist.append(space.newtuple([space.wrap(names[i]), 
space.wrap(formats[i])]))
+    return dtype_from_list(space, space.newlist(aslist), False, align=align, 
offsets=offsets)
+    
 def dtype_from_dict(space, w_dict, align):
     from pypy.objspace.std.dictmultiobject import W_DictMultiObject
     assert isinstance(w_dict, W_DictMultiObject)
@@ -638,8 +674,11 @@
     metadata_w = _get_val_or_none(space, w_dict, 'metadata')
     aligned_w = _get_val_or_none(space, w_dict, 'align')
     if names_w is None or formats_w is None:
-        return get_appbridge_cache(space).call_method(space,
-            'numpy.core._internal', '_usefields', Arguments(space, [w_dict, 
space.wrap(align)]))
+        if we_are_translated():
+            return get_appbridge_cache(space).call_method(space,
+                'numpy.core._internal', '_usefields', Arguments(space, 
[w_dict, space.wrap(align)]))
+        else:
+            return _usefields(space, w_dict, align)
     n = len(names_w)
     if (n != len(formats_w) or 
         (offsets_w is not None and n != len(offsets_w)) or
@@ -653,9 +692,10 @@
             raise oefmt(space.w_ValueError,
                     "NumPy dtype descriptor includes 'aligned' entry, "
                     "but its value is neither True nor False");
-    if offsets_w is not None:
-        raise oefmt(space.w_NotImplementedError, "'offsets' "
-            "dict entries not implemented yet") 
+    if offsets_w is None:
+        offsets = None
+    else:
+        offsets = [space.int_w(i) for i in offsets_w]
     if titles_w is not None:
         names_w = []
         for i in range(min(len(names_w), len(titles_w))):
@@ -663,34 +703,29 @@
     aslist = []
     for i in range(min(len(names_w), len(formats_w))):
         aslist.append(space.newtuple([names_w[i], formats_w[i]]))
-    retval = dtype_from_list(space, space.newlist(aslist), False, align)
+    retval = dtype_from_list(space, space.newlist(aslist), False, align=align, 
offsets=offsets)
     if metadata_w is not None:
         retval.descr_set_metadata(space, metadata_w)
     retval.flags |= NPY.NEEDS_PYAPI
     return retval 
 
-def dtype_from_spec(space, w_spec):
+def dtype_from_spec(space, w_spec, align):
 
     if we_are_translated():
         w_lst = get_appbridge_cache(space).call_method(space,
             'numpy.core._internal', '_commastring', Arguments(space, [w_spec]))
     else:
-        # testing, handle manually
-        if space.eq_w(w_spec, space.wrap('u4,u4,u4')):
-            w_lst = space.newlist([space.wrap('u4')]*3)
-        if space.eq_w(w_spec, space.wrap('u4,u4,u4')):
-            w_lst = space.newlist([space.wrap('u4')]*3)
-        else:
-            raise oefmt(space.w_RuntimeError,
-                    "cannot parse w_spec")
+        # handle only simple cases for testing
+        spec = [s.strip() for s in space.str_w(w_spec).split(',')]
+        w_lst = space.newlist([space.wrap(s) for s in spec]) 
     if not space.isinstance_w(w_lst, space.w_list) or space.len_w(w_lst) < 1:
         raise oefmt(space.w_RuntimeError,
                     "_commastring is not returning a list with len >= 1")
     if space.len_w(w_lst) == 1:
         return descr__new__(space, space.gettypefor(W_Dtype),
-                            space.getitem(w_lst, space.wrap(0)))
+                            space.getitem(w_lst, space.wrap(0)), align=align)
     else:
-        return dtype_from_list(space, w_lst, True)
+        return dtype_from_list(space, w_lst, True, align=align)
 
 
 def _check_for_commastring(s):
@@ -769,7 +804,7 @@
     if space.isinstance_w(w_dtype, space.w_str):
         name = space.str_w(w_dtype)
         if _check_for_commastring(name):
-            return _set_metadata_and_copy(dtype_from_spec(space, w_dtype), 
space, w_metadata)
+            return _set_metadata_and_copy(dtype_from_spec(space, w_dtype, 
align), space, w_metadata)
         cname = name[1:] if name[0] == NPY.OPPBYTE else name
         try:
             dtype = cache.dtypes_by_name[cname]
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
@@ -1327,6 +1327,7 @@
         dt1 = np.dtype([('f0', 'i4'),
                        ('f1', [('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')]),
                        ('f2', 'i1')], align=True)
+        assert dt1['f1'].itemsize == 12
         assert dt1.itemsize == 20
         dt2 = np.dtype({'names':['f0', 'f1', 'f2'],
                        'formats':['i4',
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to