[pypy-commit] pypy numpy-record-dtypes: boring. Add support for dtypes. A lot of refactoring, not too much of
fijal
noreply at buildbot.pypy.org
Sat Feb 18 17:35:39 CET 2012
Author: Maciej Fijalkowski <fijall at 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
More information about the pypy-commit
mailing list