Author: mattip <[email protected]>
Branch:
Changeset: r80476:393569a1c0ba
Date: 2015-10-29 16:58 +1100
http://bitbucket.org/pypy/pypy/changeset/393569a1c0ba/
Log: test, tweak handling of 'order' in various ndarray creation methods
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
@@ -23,11 +23,14 @@
'''
argsort (return the indices to sort) a list of strides
'''
- def __init__(self, rangelist, strides):
+ def __init__(self, rangelist, strides, order):
self.strides = strides
+ self.order = order
TimSort.__init__(self, rangelist)
def lt(self, a, b):
+ if self.order == NPY.CORDER:
+ return self.strides[a] <= self.strides[b]
return self.strides[a] < self.strides[b]
@@ -311,12 +314,9 @@
backstrides, shape, self, orig_array)
def copy(self, space, order=NPY.ANYORDER):
- order = support.get_order_as_CF(self.order, order)
- strides, backstrides = calc_strides(self.get_shape(), self.dtype,
- order)
- impl = ConcreteArray(self.get_shape(), self.dtype, order, strides,
- backstrides)
- return loop.setslice(space, self.get_shape(), impl, self)
+ if order == NPY.ANYORDER:
+ order = NPY.KEEPORDER
+ return self.astype(space, self.dtype, order, copy=True)
def create_iter(self, shape=None, backward_broadcast=False):
if shape is not None and \
@@ -363,7 +363,7 @@
def get_buffer(self, space, readonly):
return ArrayBuffer(self, readonly)
- def astype(self, space, dtype, order):
+ def astype(self, space, dtype, order, copy=True):
# copy the general pattern of the strides
# but make the array storage contiguous in memory
shape = self.get_shape()
@@ -377,18 +377,21 @@
t_strides, backstrides = calc_strides(shape, dtype, order)
else:
indx_array = range(len(strides))
- list_sorter = StrideSort(indx_array, strides)
+ list_sorter = StrideSort(indx_array, strides, self.order)
list_sorter.sort()
t_elsize = dtype.elsize
t_strides = strides[:]
base = dtype.elsize
+ print 'start strides, shape, indx_array', strides, shape,
indx_array
for i in indx_array:
t_strides[i] = base
base *= shape[i]
+ print 'final strides', t_strides
backstrides = calc_backstrides(t_strides, shape)
order = support.get_order_as_CF(self.order, order)
impl = ConcreteArray(shape, dtype, order, t_strides, backstrides)
- loop.setslice(space, impl.get_shape(), impl, self)
+ if copy:
+ loop.setslice(space, impl.get_shape(), impl, self)
return impl
OBJECTSTORE = lltype.GcStruct('ObjectStore',
diff --git a/pypy/module/micronumpy/ctors.py b/pypy/module/micronumpy/ctors.py
--- a/pypy/module/micronumpy/ctors.py
+++ b/pypy/module/micronumpy/ctors.py
@@ -103,15 +103,18 @@
copy = False
dtype = descriptor.decode_w_dtype(space, w_dtype)
- if space.is_none(w_order):
- w_order = space.wrap('C')
- npy_order = order_converter(space, w_order, NPY.CORDER)
if isinstance(w_object, W_NDimArray):
- if (dtype is None or w_object.get_dtype() is dtype):
- if copy and (subok or type(w_object) is W_NDimArray):
- return w_object.descr_copy(space, w_order)
- elif not copy and (subok or type(w_object) is W_NDimArray):
+ npy_order = order_converter(space, w_order, NPY.ANYORDER)
+ if (dtype is None or w_object.get_dtype() is dtype) and (subok or
+ type(w_object) is W_NDimArray):
+ flags = w_object.get_flags()
+ must_copy = copy
+ must_copy |= (npy_order == NPY.CORDER and not flags &
NPY.ARRAY_C_CONTIGUOUS)
+ must_copy |= (npy_order == NPY.FORTRANORDER and not flags &
NPY.ARRAY_F_CONTIGUOUS)
+ if must_copy:
+ return w_object.descr_copy(space, space.wrap(npy_order))
+ else:
return w_object
if subok and not type(w_object) is W_NDimArray:
raise oefmt(space.w_NotImplementedError,
@@ -124,7 +127,8 @@
copy = True
if copy:
shape = w_object.get_shape()
- w_arr = W_NDimArray.from_shape(space, shape, dtype,
order=npy_order)
+ order = support.get_order_as_CF(w_object.get_order(), npy_order)
+ w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order)
if support.product(shape) == 1:
w_arr.set_scalar_value(dtype.coerce(space,
w_object.implementation.getitem(0)))
@@ -148,6 +152,7 @@
w_base=w_base, strides=imp.strides, start=imp.start)
else:
# not an array
+ npy_order = order_converter(space, w_order, NPY.CORDER)
shape, elems_w = find_shape_and_elems(space, w_object, dtype)
if dtype is None and space.isinstance_w(w_object, space.w_buffer):
dtype = descriptor.get_dtype_cache(space).w_uint8dtype
@@ -271,6 +276,7 @@
def _zeros_or_empty(space, w_shape, w_dtype, w_order, zero):
+ # w_order can be None, str, or boolean
order = order_converter(space, w_order, NPY.CORDER)
dtype = space.interp_w(descriptor.W_Dtype,
space.call_function(space.gettypefor(descriptor.W_Dtype), w_dtype))
diff --git a/pypy/module/micronumpy/flatiter.py
b/pypy/module/micronumpy/flatiter.py
--- a/pypy/module/micronumpy/flatiter.py
+++ b/pypy/module/micronumpy/flatiter.py
@@ -16,6 +16,7 @@
self.dtype = base.get_dtype()
self.shape = [base.get_size()]
self.storage = self._base.implementation.storage
+ self.order = base.get_order()
def base(self):
return self._base
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
@@ -370,11 +370,11 @@
def descr_copy(self, space, w_order=None):
if w_order is None:
- order = NPY.KEEPORDER
+ order = NPY.CORDER
elif space.isinstance_w(w_order, space.w_int):
order = space.int_w(w_order)
else:
- order = order_converter(space, w_order, NPY.KEEPORDER)
+ order = order_converter(space, w_order, NPY.CORDER)
copy = self.implementation.copy(space, order)
w_subtype = space.type(self)
return wrap_impl(space, w_subtype, self, copy)
diff --git a/pypy/module/micronumpy/test/test_flagsobj.py
b/pypy/module/micronumpy/test/test_flagsobj.py
--- a/pypy/module/micronumpy/test/test_flagsobj.py
+++ b/pypy/module/micronumpy/test/test_flagsobj.py
@@ -47,3 +47,104 @@
b = np.array([4,5,6,7])
assert a.flags == b.flags
assert not a.flags != b.flags
+
+ def test_copy_order(self):
+ import numpy as np
+ tst = np.ones((10, 1), order='C').flags.f_contiguous
+ NPY_RELAXED_STRIDES_CHECKING = tst
+ a = np.arange(24).reshape(2, 1, 3, 4)
+ b = a.copy(order='F')
+ c = np.arange(24).reshape(2, 1, 4, 3).swapaxes(2, 3)
+
+ def check_copy_result(x, y, ccontig, fcontig, strides=False):
+ assert x is not y
+ assert (x == y).all()
+ assert res.flags.c_contiguous == ccontig
+ assert res.flags.f_contiguous == fcontig
+ # This check is impossible only because
+ # NPY_RELAXED_STRIDES_CHECKING changes the strides actively
+ if not NPY_RELAXED_STRIDES_CHECKING:
+ if strides:
+ assert x.strides == y.strides
+ else:
+ assert x.strides != y.strides
+
+ # Validate the initial state of a, b, and c
+ assert a.flags.c_contiguous
+ assert not a.flags.f_contiguous
+ assert not b.flags.c_contiguous
+ assert b.flags.f_contiguous
+ assert not c.flags.c_contiguous
+ assert not c.flags.f_contiguous
+
+ # Copy with order='C'
+ res = a.copy(order='C')
+ check_copy_result(res, a, ccontig=True, fcontig=False, strides=True)
+ res = b.copy(order='C')
+ check_copy_result(res, b, ccontig=True, fcontig=False, strides=False)
+ res = c.copy(order='C')
+ check_copy_result(res, c, ccontig=True, fcontig=False, strides=False)
+
+ # Copy with order='F'
+ res = a.copy(order='F')
+ check_copy_result(res, a, ccontig=False, fcontig=True, strides=False)
+ res = b.copy(order='F')
+ check_copy_result(res, b, ccontig=False, fcontig=True, strides=True)
+ res = c.copy(order='F')
+ check_copy_result(res, c, ccontig=False, fcontig=True, strides=False)
+
+ # Copy with order='K'
+ res = a.copy(order='K')
+ check_copy_result(res, a, ccontig=True, fcontig=False, strides=True)
+ res = b.copy(order='K')
+ check_copy_result(res, b, ccontig=False, fcontig=True, strides=True)
+ res = c.copy(order='K')
+ check_copy_result(res, c, ccontig=False, fcontig=False, strides=True)
+
+ def test_contiguous_flags(self):
+ import numpy as np
+ tst = np.ones((10, 1), order='C').flags.f_contiguous
+ NPY_RELAXED_STRIDES_CHECKING = tst
+ a = np.ones((4, 4, 1))[::2,:,:]
+ if NPY_RELAXED_STRIDES_CHECKING:
+ a.strides = a.strides[:2] + (-123,)
+ b = np.ones((2, 2, 1, 2, 2)).swapaxes(3, 4)
+
+ def check_contig(a, ccontig, fcontig):
+ assert a.flags.c_contiguous == ccontig
+ assert a.flags.f_contiguous == fcontig
+
+ # Check if new arrays are correct:
+ check_contig(a, False, False)
+ check_contig(b, False, False)
+ if NPY_RELAXED_STRIDES_CHECKING:
+ check_contig(np.empty((2, 2, 0, 2, 2)), True, True)
+ check_contig(np.array([[[1], [2]]], order='F'), True, True)
+ else:
+ check_contig(np.empty((2, 2, 0, 2, 2)), True, False)
+ check_contig(np.array([[[1], [2]]], order='F'), False, True)
+ check_contig(np.empty((2, 2)), True, False)
+ check_contig(np.empty((2, 2), order='F'), False, True)
+
+ # Check that np.array creates correct contiguous flags:
+ check_contig(np.array(a, copy=False), False, False)
+ check_contig(np.array(a, copy=False, order='C'), True, False)
+ check_contig(np.array(a, ndmin=4, copy=False, order='F'), False, True)
+
+ if NPY_RELAXED_STRIDES_CHECKING:
+ # Check slicing update of flags and :
+ check_contig(a[0], True, True)
+ check_contig(a[None, ::4, ..., None], True, True)
+ check_contig(b[0, 0, ...], False, True)
+ check_contig(b[:,:, 0:0,:,:], True, True)
+ else:
+ # Check slicing update of flags:
+ check_contig(a[0], True, False)
+ # Would be nice if this was C-Contiguous:
+ check_contig(a[None, 0, ..., None], False, False)
+ check_contig(b[0, 0, 0, ...], False, True)
+
+ # Test ravel and squeeze.
+ check_contig(a.ravel(), True, True)
+ check_contig(np.ones((1, 3, 1)).squeeze(), True, True)
+
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit