Author: Maciej Fijalkowski <[email protected]>
Branch: missing-ndarray-attributes
Changeset: r58528:dd59b7d76e43
Date: 2012-10-28 00:45 +0200
http://bitbucket.org/pypy/pypy/changeset/dd59b7d76e43/
Log: A very ugly commit :( Implement base. Unfortunately it means slice
has to carry the original array a bit everywhere
diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py
b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -44,7 +44,7 @@
def get_size(self):
return self.size // self.dtype.itemtype.get_element_size()
- def reshape(self, space, new_shape):
+ def reshape(self, space, orig_array, new_shape):
# Since we got to here, prod(new_shape) == self.size
new_strides = None
if self.size > 0:
@@ -57,7 +57,7 @@
for nd in range(ndims):
new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd]
return SliceArray(self.start, new_strides, new_backstrides,
- new_shape, self)
+ new_shape, self, orig_array)
else:
return None
@@ -168,26 +168,26 @@
i += 1
return Chunks(result)
- def descr_getitem(self, space, w_index):
+ def descr_getitem(self, space, orig_arr, w_index):
try:
item = self._single_item_index(space, w_index)
return self.getitem(item)
except IndexError:
# not a single result
chunks = self._prepare_slice_args(space, w_index)
- return chunks.apply(self)
+ return chunks.apply(orig_arr)
- def descr_setitem(self, space, w_index, w_value):
+ def descr_setitem(self, space, orig_arr, w_index, w_value):
try:
item = self._single_item_index(space, w_index)
self.setitem(item, self.dtype.coerce(space, w_value))
except IndexError:
w_value = convert_to_array(space, w_value)
chunks = self._prepare_slice_args(space, w_index)
- view = chunks.apply(self)
+ view = chunks.apply(orig_arr)
view.implementation.setslice(space, w_value)
- def transpose(self):
+ def transpose(self, orig_array):
if len(self.shape) < 2:
return self
strides = []
@@ -198,7 +198,7 @@
backstrides.append(self.backstrides[i])
shape.append(self.shape[i])
return SliceArray(self.start, strides,
- backstrides, shape, self)
+ backstrides, shape, self, orig_array)
def copy(self):
strides, backstrides = support.calc_strides(self.shape, self.dtype,
@@ -215,7 +215,7 @@
shape, skip)
return iter.MultiDimViewIterator(self, self.start, r[0], r[1], shape)
- def swapaxes(self, axis1, axis2):
+ def swapaxes(self, orig_arr, axis1, axis2):
shape = self.shape[:]
strides = self.strides[:]
backstrides = self.backstrides[:]
@@ -223,7 +223,7 @@
strides[axis1], strides[axis2] = strides[axis2], strides[axis1]
backstrides[axis1], backstrides[axis2] = backstrides[axis2],
backstrides[axis1]
return W_NDimArray.new_slice(self.start, strides,
- backstrides, shape, self)
+ backstrides, shape, self, orig_arr)
def get_storage_as_int(self, space):
return rffi.cast(lltype.Signed, self.storage)
@@ -254,10 +254,11 @@
def __del__(self):
free_raw_storage(self.storage, track_allocation=False)
- def set_shape(self, space, new_shape):
+ def set_shape(self, space, orig_array, new_shape):
strides, backstrides = support.calc_strides(new_shape, self.dtype,
self.order)
- return SliceArray(0, strides, backstrides, new_shape, self)
+ return SliceArray(0, strides, backstrides, new_shape, self,
+ orig_array)
def argsort(self, space, w_axis):
return argsort_array(self, space, w_axis)
@@ -267,8 +268,12 @@
loop.copy_from_to(self, new_arr.implementation, dtype)
return new_arr
+ def base(self):
+ return None
+
class SliceArray(BaseConcreteArray):
- def __init__(self, start, strides, backstrides, shape, parent, dtype=None):
+ def __init__(self, start, strides, backstrides, shape, parent, orig_arr,
+ dtype=None):
self.strides = strides
self.backstrides = backstrides
self.shape = shape
@@ -282,6 +287,10 @@
self.dtype = dtype
self.size = support.product(shape) *
self.dtype.itemtype.get_element_size()
self.start = start
+ self.orig_arr = orig_arr
+
+ def base(self):
+ return self.orig_arr
def fill(self, box):
loop.fill(self, box.convert_to(self.dtype))
@@ -297,7 +306,7 @@
return iter.MultiDimViewIterator(self.parent, self.start, self.strides,
self.backstrides, self.shape)
- def set_shape(self, space, new_shape):
+ def set_shape(self, space, orig_array, new_shape):
if len(self.shape) < 2 or self.size == 0:
# TODO: this code could be refactored into calc_strides
# but then calc_strides would have to accept a stepping factor
@@ -316,7 +325,7 @@
backstrides.reverse()
new_shape.reverse()
return SliceArray(self.start, strides, backstrides, new_shape,
- self)
+ self, orig_array)
new_strides = calc_new_strides(new_shape, self.shape, self.strides,
self.order)
if new_strides is None:
@@ -326,4 +335,4 @@
for nd in range(len(new_shape)):
new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd]
return SliceArray(self.start, new_strides, new_backstrides, new_shape,
- self)
+ self, orig_array)
diff --git a/pypy/module/micronumpy/arrayimpl/scalar.py
b/pypy/module/micronumpy/arrayimpl/scalar.py
--- a/pypy/module/micronumpy/arrayimpl/scalar.py
+++ b/pypy/module/micronumpy/arrayimpl/scalar.py
@@ -51,10 +51,10 @@
def get_size(self):
return 1
- def transpose(self):
+ def transpose(self, _):
return self
- def descr_getitem(self, space, w_idx):
+ def descr_getitem(self, space, _, w_idx):
raise OperationError(space.w_IndexError,
space.wrap("scalars cannot be indexed"))
@@ -62,14 +62,14 @@
raise OperationError(space.w_IndexError,
space.wrap("scalars cannot be indexed"))
- def descr_setitem(self, space, w_idx, w_val):
+ def descr_setitem(self, space, _, w_idx, w_val):
raise OperationError(space.w_IndexError,
space.wrap("scalars cannot be indexed"))
def setitem_index(self, space, idx, w_val):
raise OperationError(space.w_IndexError,
space.wrap("scalars cannot be indexed"))
- def set_shape(self, space, new_shape):
+ def set_shape(self, space, orig_array, new_shape):
if not new_shape:
return self
if support.product(new_shape) == 1:
@@ -80,8 +80,8 @@
raise OperationError(space.w_ValueError, space.wrap(
"total size of the array must be unchanged"))
- def reshape(self, space, new_shape):
- return self.set_shape(space, new_shape)
+ def reshape(self, space, orig_array, new_shape):
+ return self.set_shape(space, orig_array, new_shape)
def create_axis_iter(self, shape, dim):
raise Exception("axis iter should not happen on scalar")
@@ -101,3 +101,6 @@
def astype(self, space, dtype):
return W_NDimArray.new_scalar(space, dtype, self.value)
+
+ def base(self):
+ return None
diff --git a/pypy/module/micronumpy/arrayimpl/sort.py
b/pypy/module/micronumpy/arrayimpl/sort.py
--- a/pypy/module/micronumpy/arrayimpl/sort.py
+++ b/pypy/module/micronumpy/arrayimpl/sort.py
@@ -73,7 +73,9 @@
raise OperationError(space.w_NotImplementedError,
space.wrap("sorting of non-numeric types is not implemented"))
if w_axis is space.w_None:
- arr = arr.reshape(space, [arr.get_size()])
+ # note that it's fine ot pass None here as we're not going
+ # to pass the result around (None is the link to base in slices)
+ arr = arr.reshape(space, None, [arr.get_size()])
axis = 0
elif w_axis is None:
axis = -1
diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py
--- a/pypy/module/micronumpy/base.py
+++ b/pypy/module/micronumpy/base.py
@@ -23,11 +23,12 @@
return W_NDimArray(impl)
@staticmethod
- def new_slice(offset, strides, backstrides, shape, parent, dtype=None):
+ def new_slice(offset, strides, backstrides, shape, parent, orig_arr,
+ dtype=None):
from pypy.module.micronumpy.arrayimpl import concrete
impl = concrete.SliceArray(offset, strides, backstrides, shape, parent,
- dtype)
+ orig_arr, dtype)
return W_NDimArray(impl)
@staticmethod
diff --git a/pypy/module/micronumpy/interp_arrayops.py
b/pypy/module/micronumpy/interp_arrayops.py
--- a/pypy/module/micronumpy/interp_arrayops.py
+++ b/pypy/module/micronumpy/interp_arrayops.py
@@ -123,7 +123,7 @@
for arr in args_w:
chunks[axis] = Chunk(axis_start, axis_start + arr.get_shape()[axis], 1,
arr.get_shape()[axis])
-
Chunks(chunks).apply(res.implementation).implementation.setslice(space, arr)
+ Chunks(chunks).apply(res).implementation.setslice(space, arr)
axis_start += arr.get_shape()[axis]
return res
@@ -137,7 +137,7 @@
res = W_NDimArray.from_shape(shape, arr.get_dtype())
for i in range(repeats):
Chunks([Chunk(i, shape[0] - repeats + i, repeats,
-
orig_size)]).apply(res.implementation).implementation.setslice(space, arr)
+
orig_size)]).apply(res).implementation.setslice(space, arr)
else:
axis = space.int_w(w_axis)
shape = arr.get_shape()[:]
@@ -148,7 +148,7 @@
for i in range(repeats):
chunks[axis] = Chunk(i, shape[axis] - repeats + i, repeats,
orig_size)
-
Chunks(chunks).apply(res.implementation).implementation.setslice(space, arr)
+ Chunks(chunks).apply(res).implementation.setslice(space, arr)
return res
def count_nonzero(space, w_obj):
diff --git a/pypy/module/micronumpy/interp_dtype.py
b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -232,8 +232,6 @@
return dtype
if w_dtype is dtype.w_box_type:
return dtype
- import pdb
- pdb.set_trace()
raise OperationError(space.w_TypeError, space.wrap("data type not
understood"))
W_Dtype.typedef = TypeDef("dtype",
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
@@ -37,7 +37,7 @@
return self.implementation.get_shape()
def descr_set_shape(self, space, w_new_shape):
- self.implementation = self.implementation.set_shape(space,
+ self.implementation = self.implementation.set_shape(space, self,
get_shape_from_iterable(space, self.get_size(), w_new_shape))
def get_dtype(self):
@@ -148,7 +148,7 @@
w_idx.get_dtype().is_bool_type()):
return self.getitem_filter(space, w_idx)
try:
- return self.implementation.descr_getitem(space, w_idx)
+ return self.implementation.descr_getitem(space, self, w_idx)
except ArrayArgumentException:
return self.getitem_array_int(space, w_idx)
except OperationError:
@@ -166,7 +166,7 @@
return self.setitem_filter(space, w_idx,
convert_to_array(space, w_value))
try:
- self.implementation.descr_setitem(space, w_idx, w_value)
+ self.implementation.descr_setitem(space, self, w_idx, w_value)
except ArrayArgumentException:
self.setitem_array_int(space, w_idx, w_value)
@@ -254,20 +254,21 @@
else:
w_shape = space.newtuple(args_w)
new_shape = get_shape_from_iterable(space, self.get_size(), w_shape)
- new_impl = self.implementation.reshape(space, new_shape)
+ new_impl = self.implementation.reshape(space, self, new_shape)
if new_impl is not None:
return W_NDimArray(new_impl)
# Create copy with contiguous data
arr = self.descr_copy(space)
if arr.get_size() > 0:
- arr.implementation = arr.implementation.reshape(space, new_shape)
+ arr.implementation = arr.implementation.reshape(space, self,
+ new_shape)
assert arr.implementation
else:
arr.implementation.shape = new_shape
return arr
def descr_get_transpose(self, space):
- return W_NDimArray(self.implementation.transpose())
+ return W_NDimArray(self.implementation.transpose(self))
@unwrap_spec(axis1=int, axis2=int)
def descr_swapaxes(self, space, axis1, axis2):
@@ -283,7 +284,7 @@
"""
if self.is_scalar():
return self
- return self.implementation.swapaxes(axis1, axis2)
+ return self.implementation.swapaxes(self, axis1, axis2)
def descr_tolist(self, space):
if len(self.get_shape()) == 0:
@@ -389,9 +390,8 @@
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype))
return self.implementation.astype(space, dtype)
- def descr_base(self, space):
- raise OperationError(space.w_NotImplementedError, space.wrap(
- "base not implemented yet"))
+ def descr_get_base(self, space):
+ return self.implementation.base()
def descr_byteswap(self, space, w_inplace=False):
raise OperationError(space.w_NotImplementedError, space.wrap(
@@ -790,6 +790,7 @@
argsort = interp2app(W_NDimArray.descr_argsort),
astype = interp2app(W_NDimArray.descr_astype),
+ base = GetSetProperty(W_NDimArray.descr_get_base),
__array_interface__ = GetSetProperty(W_NDimArray.descr_array_iface),
)
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
@@ -57,12 +57,13 @@
def __init__(self, name):
self.name = name
- def apply(self, arr):
+ def apply(self, 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(arr.start + ofs, arr.strides,
arr.backstrides,
- arr.shape, arr, subdtype)
+ arr.shape, arr, orig_arr, subdtype)
class Chunks(BaseChunk):
def __init__(self, l):
@@ -79,13 +80,14 @@
assert s >= 0
return shape[:] + old_shape[s:]
- def apply(self, arr):
+ def apply(self, orig_arr):
+ arr = orig_arr.implementation
shape = self.extend_shape(arr.shape)
r = calculate_slice_strides(arr.shape, arr.start, arr.strides,
arr.backstrides, self.l)
_, start, strides, backstrides = r
return W_NDimArray.new_slice(start, strides[:], backstrides[:],
- shape[:], arr)
+ shape[:], arr, orig_arr)
class Chunk(BaseChunk):
diff --git a/pypy/module/micronumpy/test/test_iter.py
b/pypy/module/micronumpy/test/test_iter.py
--- a/pypy/module/micronumpy/test/test_iter.py
+++ b/pypy/module/micronumpy/test/test_iter.py
@@ -1,4 +1,4 @@
-from pypy.module.micronumpy.arrayimpl.concrete import MultiDimViewIterator
+from pypy.module.micronumpy.iter import MultiDimViewIterator
class MockArray(object):
size = 1
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
@@ -22,7 +22,7 @@
def create_slice(a, chunks):
- return Chunks(chunks).apply(a).implementation
+ return Chunks(chunks).apply(W_NDimArray(a)).implementation
def create_array(*args, **kwargs):
return W_NDimArray.from_shape(*args, **kwargs).implementation
@@ -1576,6 +1576,14 @@
assert (b == [1, 2]).all()
assert b.dtype == 'float'
+ def test_base(self):
+ from _numpypy import array
+ assert array(1).base is None
+ assert array([1, 2]).base is None
+ a = array([1, 2, 3, 4])
+ b = a[::2]
+ assert b.base is a
+
class AppTestMultiDim(BaseNumpyAppTest):
def test_init(self):
import _numpypy
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit