Author: Maciej Fijalkowski <fij...@gmail.com> Branch: numpy-record-dtypes Changeset: r52611:2f1522449cee Date: 2012-02-18 18:35 +0200 http://bitbucket.org/pypy/pypy/changeset/2f1522449cee/
Log: boring. Add support for dtypes. A lot of refactoring, not too much of actual code. diff --git a/pypy/module/micronumpy/interp_iter.py b/pypy/module/micronumpy/interp_iter.py --- a/pypy/module/micronumpy/interp_iter.py +++ b/pypy/module/micronumpy/interp_iter.py @@ -49,17 +49,58 @@ # structures to describe slicing -class Chunk(object): +class BaseChunk(object): + pass + +class RecordChunk(BaseChunk): + def __init__(self, name): + self.name = name + + def apply(self, arr): + from pypy.module.micronumpy.interp_numarray import W_NDimSlice + + arr = arr.get_concrete() + ofs, subdtype = arr.dtype.fields[self.name] + # strides backstrides are identical, ofs only changes start + return W_NDimSlice(arr.start + ofs, arr.strides[:], arr.backstrides[:], + arr.shape[:], arr, subdtype) + +class Chunks(BaseChunk): + def __init__(self, l): + self.l = l + + @jit.unroll_safe + def extend_shape(self, old_shape): + shape = [] + i = -1 + for i, c in enumerate(self.l): + if c.step != 0: + shape.append(c.lgt) + s = i + 1 + assert s >= 0 + return shape[:] + old_shape[s:] + + def apply(self, space, arr): + from pypy.module.micronumpy.interp_numarray import W_NDimSlice,\ + VirtualSlice, ConcreteArray + + shape = self.extend_shape(arr.shape) + if not isinstance(arr, ConcreteArray): + return VirtualSlice(arr, self, shape) + r = calculate_slice_strides(arr.shape, arr.start, arr.strides, + arr.backstrides, self.l) + _, start, strides, backstrides = r + return W_NDimSlice(start, strides[:], backstrides[:], + shape[:], arr) + + +class Chunk(BaseChunk): def __init__(self, start, stop, step, lgt): self.start = start self.stop = stop self.step = step self.lgt = lgt - def extend_shape(self, shape): - if self.step != 0: - shape.append(self.lgt) - def __repr__(self): return 'Chunk(%d, %d, %d, %d)' % (self.start, self.stop, self.step, self.lgt) 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 @@ -13,7 +13,7 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.rstring import StringBuilder from pypy.module.micronumpy.interp_iter import (ArrayIterator, - SkipLastAxisIterator, Chunk, ViewIterator) + SkipLastAxisIterator, Chunks, Chunk, ViewIterator, RecordChunk) from pypy.module.micronumpy.appbridge import get_appbridge_cache @@ -328,11 +328,18 @@ @jit.unroll_safe def _prepare_slice_args(self, space, w_idx): + if space.isinstance_w(w_idx, space.w_str): + idx = space.str_w(w_idx) + dtype = self.find_dtype() + if not dtype.is_record_type() or idx not in dtype.fields: + raise OperationError(space.w_ValueError, space.wrap( + "field named %s not defined" % idx)) + return RecordChunk(idx) if (space.isinstance_w(w_idx, space.w_int) or space.isinstance_w(w_idx, space.w_slice)): - return [Chunk(*space.decode_index4(w_idx, self.shape[0]))] - return [Chunk(*space.decode_index4(w_item, self.shape[i])) for i, w_item in - enumerate(space.fixedview(w_idx))] + return Chunks([Chunk(*space.decode_index4(w_idx, self.shape[0]))]) + return Chunks([Chunk(*space.decode_index4(w_item, self.shape[i])) for i, w_item in + enumerate(space.fixedview(w_idx))]) def count_all_true(self): sig = self.find_sig() @@ -375,6 +382,17 @@ frame.next(shapelen) return res + def descr_getitem(self, space, w_idx): + if (isinstance(w_idx, BaseArray) and w_idx.shape == self.shape and + w_idx.find_dtype().is_bool_type()): + return self.getitem_filter(space, w_idx) + if self._single_item_result(space, w_idx): + concrete = self.get_concrete() + item = concrete._index_of_single_item(space, w_idx) + return concrete.getitem(item) + chunks = self._prepare_slice_args(space, w_idx) + return chunks.apply(self) + def setitem_filter(self, space, idx, val): size = idx.count_all_true() arr = SliceArray([size], self.dtype, self, val) @@ -392,17 +410,6 @@ frame.next_first(shapelen) idxi = idxi.next(shapelen) - def descr_getitem(self, space, w_idx): - if (isinstance(w_idx, BaseArray) and w_idx.shape == self.shape and - w_idx.find_dtype().is_bool_type()): - return self.getitem_filter(space, w_idx) - if self._single_item_result(space, w_idx): - concrete = self.get_concrete() - item = concrete._index_of_single_item(space, w_idx) - return concrete.getitem(item) - chunks = self._prepare_slice_args(space, w_idx) - return self.create_slice(chunks) - def descr_setitem(self, space, w_idx, w_value): self.invalidated() if (isinstance(w_idx, BaseArray) and w_idx.shape == self.shape and @@ -419,26 +426,9 @@ if not isinstance(w_value, BaseArray): w_value = convert_to_array(space, w_value) chunks = self._prepare_slice_args(space, w_idx) - view = self.create_slice(chunks).get_concrete() + view = chunks.apply(self).get_concrete() view.setslice(space, w_value) - @jit.unroll_safe - def create_slice(self, chunks): - shape = [] - i = -1 - for i, chunk in enumerate(chunks): - chunk.extend_shape(shape) - s = i + 1 - assert s >= 0 - shape += self.shape[s:] - if not isinstance(self, ConcreteArray): - return VirtualSlice(self, chunks, shape) - r = calculate_slice_strides(self.shape, self.start, self.strides, - self.backstrides, chunks) - _, start, strides, backstrides = r - return W_NDimSlice(start, strides[:], backstrides[:], - shape[:], self) - def descr_reshape(self, space, args_w): """reshape(...) a.reshape(shape) @@ -741,7 +731,7 @@ def force_if_needed(self): if self.forced_result is None: concr = self.child.get_concrete() - self.forced_result = concr.create_slice(self.chunks) + self.forced_result = self.chunks.apply(concr) def _del_sources(self): self.child = None @@ -1020,13 +1010,15 @@ class W_NDimSlice(ViewArray): - def __init__(self, start, strides, backstrides, shape, parent): + def __init__(self, start, strides, backstrides, shape, parent, dtype=None): assert isinstance(parent, ConcreteArray) if isinstance(parent, W_NDimSlice): parent = parent.parent self.strides = strides self.backstrides = backstrides - ViewArray.__init__(self, shape, parent.dtype, parent.order, parent) + if dtype is None: + dtype = parent.dtype + ViewArray.__init__(self, shape, dtype, parent.order, parent) self.start = start def create_iter(self, transforms=None): @@ -1231,7 +1223,7 @@ for arr in args_w: chunks[axis] = Chunk(axis_start, axis_start + arr.shape[axis], 1, arr.shape[axis]) - res.create_slice(chunks).setslice(space, arr) + chunks.apply(res).setslice(space, arr) axis_start += arr.shape[axis] return res 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 @@ -1815,7 +1815,18 @@ assert a[1]['y'] == 2 def test_views(self): - skip("xx") + from _numpypy import array + a = array([(1, 2), (3, 4)], dtype=[('x', int), ('y', float)]) + raises(ValueError, 'array([1])["x"]') + raises(ValueError, 'a["z"]') + assert a['x'][1] == 3 + assert a['y'][1] == 4 + a['x'][0] = 15 + assert a['x'][0] == 15 + b = a['x'] + a['y'] + print b, a + assert (b == [15+2, 3+4]).all() + assert b.dtype == float def test_creation(self): from _numpypy import array _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit