[pypy-commit] pypy default: implement strides argument when buffer=something for ndarray constructor,
fijal
noreply at buildbot.pypy.org
Tue Dec 2 14:31:03 CET 2014
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch:
Changeset: r74782:86fcd1d9f5df
Date: 2014-12-02 15:29 +0200
http://bitbucket.org/pypy/pypy/changeset/86fcd1d9f5df/
Log: implement strides argument when buffer=something for ndarray
constructor, also for from_shape_and_storage
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
@@ -44,11 +44,16 @@
return W_NDimArray(impl)
@staticmethod
- def from_shape_and_storage(space, shape, storage, dtype, order='C', owning=False,
- w_subtype=None, w_base=None, writable=True):
+ def from_shape_and_storage(space, shape, storage, dtype, order='C',
+ owning=False, w_subtype=None, w_base=None,
+ writable=True, strides=None):
from pypy.module.micronumpy import concrete
- from pypy.module.micronumpy.strides import calc_strides
- strides, backstrides = calc_strides(shape, dtype, order)
+ from pypy.module.micronumpy.strides import (calc_strides,
+ calc_backstrides)
+ if strides is None:
+ strides, backstrides = calc_strides(shape, dtype, order)
+ else:
+ backstrides = calc_backstrides(strides, shape)
if w_base is not None:
if owning:
raise OperationError(space.w_ValueError,
diff --git a/pypy/module/micronumpy/concrete.py b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -11,7 +11,7 @@
from pypy.module.micronumpy.iterators import ArrayIter
from pypy.module.micronumpy.strides import (Chunk, Chunks, NewAxisChunk,
RecordChunk, calc_strides, calc_new_strides, shape_agreement,
- calculate_broadcast_strides)
+ calculate_broadcast_strides, calc_backstrides)
class BaseConcreteArray(object):
@@ -79,10 +79,7 @@
self.get_strides(), self.order)
if new_strides is not None:
# We can create a view, strides somehow match up.
- ndims = len(new_shape)
- new_backstrides = [0] * ndims
- for nd in range(ndims):
- new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd]
+ new_backstrides = calc_backstrides(new_strides, new_shape)
assert isinstance(orig_array, W_NDimArray) or orig_array is None
return SliceArray(self.start, new_strides, new_backstrides,
new_shape, self, orig_array)
diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -1213,8 +1213,10 @@
if not space.is_none(w_buffer):
if (not space.is_none(w_strides)):
- raise OperationError(space.w_NotImplementedError,
- space.wrap("unsupported param"))
+ strides = [space.int_w(w_i) for w_i in
+ space.unpackiterable(w_strides)]
+ else:
+ strides = None
try:
buf = space.writebuf_w(w_buffer)
@@ -1237,7 +1239,8 @@
return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype,
w_subtype=w_subtype,
w_base=w_buffer,
- writable=not buf.readonly)
+ writable=not buf.readonly,
+ strides=strides)
order = order_converter(space, w_order, NPY.CORDER)
if order == NPY.CORDER:
@@ -1256,7 +1259,7 @@
@unwrap_spec(addr=int)
-def descr__from_shape_and_storage(space, w_cls, w_shape, addr, w_dtype, w_subtype=None):
+def descr__from_shape_and_storage(space, w_cls, w_shape, addr, w_dtype, w_subtype=None, w_strides=None):
"""
Create an array from an existing buffer, given its address as int.
PyPy-only implementation detail.
@@ -1265,14 +1268,21 @@
dtype = space.interp_w(descriptor.W_Dtype, space.call_function(
space.gettypefor(descriptor.W_Dtype), w_dtype))
shape = shape_converter(space, w_shape, dtype)
+ if not space.is_none(w_strides):
+ strides = [space.int_w(w_i) for w_i in
+ space.unpackiterable(w_strides)]
+ else:
+ strides = None
if w_subtype:
if not space.isinstance_w(w_subtype, space.w_type):
raise OperationError(space.w_ValueError, space.wrap(
"subtype must be a subtype of ndarray, not a class instance"))
return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype,
- 'C', False, w_subtype)
+ 'C', False, w_subtype,
+ strides=strides)
else:
- return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype)
+ return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype,
+ strides=strides)
app_take = applevel(r"""
def take(a, indices, axis, out, mode):
diff --git a/pypy/module/micronumpy/strides.py b/pypy/module/micronumpy/strides.py
--- a/pypy/module/micronumpy/strides.py
+++ b/pypy/module/micronumpy/strides.py
@@ -362,6 +362,13 @@
backstrides.reverse()
return strides, backstrides
+ at jit.unroll_safe
+def calc_backstrides(strides, shape):
+ ndims = len(shape)
+ new_backstrides = [0] * ndims
+ for nd in range(ndims):
+ new_backstrides[nd] = (shape[nd] - 1) * strides[nd]
+ return new_backstrides
# Recalculating strides. Find the steps that the iteration does for each
# dimension, given the stride and shape. Then try to create a new stride that
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -3926,3 +3926,27 @@
assert x.__pypy_data__ is obj
del x.__pypy_data__
assert x.__pypy_data__ is None
+
+ def test_ndarray_buffer_strides(self):
+ from numpypy import ndarray, array
+ base = array([1, 2, 3, 4], dtype=int)
+ a = ndarray((4,), buffer=base, dtype=int)
+ assert a[1] == 2
+ a = ndarray((4,), buffer=base, dtype=int, strides=[base.strides[0]])
+ assert a[1] == 2
+ a = ndarray((4,), buffer=base, dtype=int, strides=[2 * base.strides[0]])
+ assert a[1] == 3
+
+ def test_from_shape_and_storage_strides(self):
+ from numpypy import ndarray, array
+ base = array([1, 2, 3, 4], dtype=int)
+ addr, _ = base.__array_interface__['data']
+ a = ndarray._from_shape_and_storage((4,), addr, int)
+ assert a[1] == 2
+ a = ndarray._from_shape_and_storage((4,), addr, int,
+ strides=[base.strides[0]])
+ assert a[1] == 2
+ a = ndarray._from_shape_and_storage((4,), addr, int,
+ strides=[2 * base.strides[0]])
+ assert a[1] == 3
+
More information about the pypy-commit
mailing list