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