Author: mattip <[email protected]>
Branch:
Changeset: r80082:26b886602ace
Date: 2015-10-09 14:51 +0300
http://bitbucket.org/pypy/pypy/changeset/26b886602ace/
Log: merge fortran-order into default
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -60,3 +60,7 @@
.. branch: callfamily
Refactorings of annotation and rtyping of function calls.
+
+.. branch: fortran-order
+
+Allow creation of fortran-ordered ndarrays
diff --git a/pypy/module/cpyext/ndarrayobject.py
b/pypy/module/cpyext/ndarrayobject.py
--- a/pypy/module/cpyext/ndarrayobject.py
+++ b/pypy/module/cpyext/ndarrayobject.py
@@ -12,6 +12,7 @@
from pypy.module.micronumpy.descriptor import get_dtype_cache, W_Dtype
from pypy.module.micronumpy.concrete import ConcreteArray
from pypy.module.micronumpy import ufuncs
+import pypy.module.micronumpy.constants as NPY
from rpython.rlib.rawstorage import RAW_STORAGE_PTR
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.baseobjspace import W_Root
@@ -203,12 +204,12 @@
return shape, dtype
def simple_new(space, nd, dims, typenum,
- order='C', owning=False, w_subtype=None):
+ order=NPY.CORDER, owning=False, w_subtype=None):
shape, dtype = get_shape_and_dtype(space, nd, dims, typenum)
return W_NDimArray.from_shape(space, shape, dtype)
def simple_new_from_data(space, nd, dims, typenum, data,
- order='C', owning=False, w_subtype=None):
+ order=NPY.CORDER, owning=False, w_subtype=None):
shape, dtype = get_shape_and_dtype(space, nd, dims, typenum)
storage = rffi.cast(RAW_STORAGE_PTR, data)
return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype,
@@ -238,7 +239,7 @@
raise OperationError(space.w_NotImplementedError,
space.wrap("strides must be NULL"))
- order = 'C' if flags & NPY_C_CONTIGUOUS else 'F'
+ order = NPY.CORDER if flags & NPY_C_CONTIGUOUS else NPY.FORTRANORDER
owning = True if flags & NPY_OWNDATA else False
w_subtype = None
diff --git a/pypy/module/cpyext/test/test_ndarrayobject.py
b/pypy/module/cpyext/test/test_ndarrayobject.py
--- a/pypy/module/cpyext/test/test_ndarrayobject.py
+++ b/pypy/module/cpyext/test/test_ndarrayobject.py
@@ -4,16 +4,17 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.micronumpy.ndarray import W_NDimArray
from pypy.module.micronumpy.descriptor import get_dtype_cache
+import pypy.module.micronumpy.constants as NPY
def scalar(space):
dtype = get_dtype_cache(space).w_float64dtype
return W_NDimArray.new_scalar(space, dtype, space.wrap(10.))
-def array(space, shape, order='C'):
+def array(space, shape, order=NPY.CORDER):
dtype = get_dtype_cache(space).w_float64dtype
return W_NDimArray.from_shape(space, shape, dtype, order=order)
-def iarray(space, shape, order='C'):
+def iarray(space, shape, order=NPY.CORDER):
dtype = get_dtype_cache(space).w_int64dtype
return W_NDimArray.from_shape(space, shape, dtype, order=order)
@@ -32,8 +33,8 @@
def test_FLAGS(self, space, api):
s = array(space, [10])
- c = array(space, [10, 5, 3], order='C')
- f = array(space, [10, 5, 3], order='F')
+ c = array(space, [10, 5, 3], order=NPY.CORDER)
+ f = array(space, [10, 5, 3], order=NPY.FORTRANORDER)
assert api._PyArray_FLAGS(s) & 0x0001
assert api._PyArray_FLAGS(s) & 0x0002
assert api._PyArray_FLAGS(c) & 0x0001
diff --git a/pypy/module/micronumpy/arrayops.py
b/pypy/module/micronumpy/arrayops.py
--- a/pypy/module/micronumpy/arrayops.py
+++ b/pypy/module/micronumpy/arrayops.py
@@ -108,7 +108,8 @@
w_axis = space.wrap(0)
if space.is_none(w_axis):
args_w = [w_arg.reshape(space,
- space.newlist([w_arg.descr_get_size(space)]))
+ space.newlist([w_arg.descr_get_size(space)]),
+ w_arg.get_order())
for w_arg in args_w]
w_axis = space.wrap(0)
dtype = args_w[0].get_dtype()
@@ -140,7 +141,7 @@
dtype = find_result_type(space, args_w, [])
# concatenate does not handle ndarray subtypes, it always returns a ndarray
- res = W_NDimArray.from_shape(space, shape, dtype, 'C')
+ res = W_NDimArray.from_shape(space, shape, dtype, NPY.CORDER)
chunks = [Chunk(0, i, 1, i) for i in shape]
axis_start = 0
for arr in args_w:
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
@@ -38,7 +38,8 @@
self.implementation = implementation
@staticmethod
- def from_shape(space, shape, dtype, order='C', w_instance=None, zero=True):
+ def from_shape(space, shape, dtype, order=NPY.CORDER,
+ w_instance=None, zero=True):
from pypy.module.micronumpy import concrete, descriptor, boxes
from pypy.module.micronumpy.strides import calc_strides
if len(shape) > NPY.MAXDIMS:
@@ -59,8 +60,9 @@
@staticmethod
def from_shape_and_storage(space, shape, storage, dtype, storage_bytes=-1,
- order='C', owning=False, w_subtype=None,
- w_base=None, writable=True, strides=None,
start=0):
+ order=NPY.CORDER, owning=False, w_subtype=None,
+ w_base=None, writable=True, strides=None,
+ start=0):
from pypy.module.micronumpy import concrete
from pypy.module.micronumpy.strides import (calc_strides,
calc_backstrides)
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
@@ -56,6 +56,9 @@
jit.hint(len(backstrides), promote=True)
return backstrides
+ def get_flags(self):
+ return self.flags
+
def getitem(self, index):
return self.dtype.read(self, index, 0)
@@ -89,17 +92,18 @@
def get_storage_size(self):
return self.size
- def reshape(self, orig_array, new_shape):
+ def reshape(self, orig_array, new_shape, order=NPY.ANYORDER):
# Since we got to here, prod(new_shape) == self.size
+ order = support.get_order_as_CF(self.order, order)
new_strides = None
if self.size == 0:
- new_strides, _ = calc_strides(new_shape, self.dtype, self.order)
+ new_strides, _ = calc_strides(new_shape, self.dtype, order)
else:
if len(self.get_shape()) == 0:
new_strides = [self.dtype.elsize] * len(new_shape)
else:
new_strides = calc_new_strides(new_shape, self.get_shape(),
- self.get_strides(), self.order)
+ self.get_strides(), order)
if new_strides is None or len(new_strides) != len(new_shape):
return None
if new_strides is not None:
@@ -303,10 +307,11 @@
return SliceArray(self.start, strides,
backstrides, shape, self, orig_array)
- def copy(self, space):
+ 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,
- self.order)
- impl = ConcreteArray(self.get_shape(), self.dtype, self.order, strides,
+ order)
+ impl = ConcreteArray(self.get_shape(), self.dtype, order, strides,
backstrides)
return loop.setslice(space, self.get_shape(), impl, self)
@@ -360,12 +365,12 @@
# but make the array storage contiguous in memory
shape = self.get_shape()
strides = self.get_strides()
- if order not in ('C', 'F'):
- raise oefmt(space.w_ValueError, "Unknown order %s in astype",
order)
+ if order not in (NPY.KEEPORDER, NPY.FORTRANORDER, NPY.CORDER):
+ raise oefmt(space.w_ValueError, "Unknown order %d in astype",
order)
if len(strides) == 0:
t_strides = []
backstrides = []
- elif order != self.order:
+ elif order in (NPY.FORTRANORDER, NPY.CORDER):
t_strides, backstrides = calc_strides(shape, dtype, order)
else:
indx_array = range(len(strides))
@@ -378,6 +383,7 @@
t_strides[i] = base
base *= shape[i]
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)
return impl
@@ -429,6 +435,8 @@
self.shape = shape
# already tested for overflow in from_shape_and_storage
self.size = support.product(shape) * dtype.elsize
+ if order not in (NPY.CORDER, NPY.FORTRANORDER):
+ raise oefmt(dtype.itemtype.space.w_ValueError,
"ConcreteArrayNotOwning but order is not 0,1 rather %d", order)
self.order = order
self.dtype = dtype
self.strides = strides
@@ -562,6 +570,8 @@
self.parent = parent
self.storage = parent.storage
self.gcstruct = parent.gcstruct
+ if parent.order not in (NPY.CORDER, NPY.FORTRANORDER):
+ raise oefmt(dtype.itemtype.space.w_ValueError, "SliceArray but
parent order is not 0,1 rather %d", parent.order)
self.order = parent.order
self.dtype = dtype
try:
@@ -602,13 +612,13 @@
s = self.get_strides()[0] // dtype.elsize
except IndexError:
s = 1
- if self.order == 'C':
+ if self.order != NPY.FORTRANORDER:
new_shape.reverse()
for sh in new_shape:
strides.append(s * dtype.elsize)
backstrides.append(s * (sh - 1) * dtype.elsize)
s *= max(1, sh)
- if self.order == 'C':
+ if self.order != NPY.FORTRANORDER:
strides.reverse()
backstrides.reverse()
new_shape.reverse()
diff --git a/pypy/module/micronumpy/converters.py
b/pypy/module/micronumpy/converters.py
--- a/pypy/module/micronumpy/converters.py
+++ b/pypy/module/micronumpy/converters.py
@@ -77,9 +77,8 @@
elif order.startswith('K') or order.startswith('k'):
return NPY.KEEPORDER
else:
- raise OperationError(space.w_TypeError, space.wrap(
- "order not understood"))
-
+ raise oefmt(space.w_TypeError, "Unknown order: '%s'", order)
+ return -1
def multi_axis_converter(space, w_axis, ndim):
if space.is_none(w_axis):
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
@@ -5,10 +5,10 @@
from rpython.rtyper.lltypesystem import lltype, rffi
from pypy.module.micronumpy import descriptor, loop, support
-from pypy.module.micronumpy.base import (
+from pypy.module.micronumpy.base import (wrap_impl,
W_NDimArray, convert_to_array, W_NumpyObject)
-from pypy.module.micronumpy.converters import shape_converter
-from . import constants as NPY
+from pypy.module.micronumpy.converters import shape_converter, order_converter
+import pypy.module.micronumpy.constants as NPY
from .casting import scalar2dtype
@@ -101,13 +101,8 @@
dtype = descriptor.decode_w_dtype(space, w_dtype)
if space.is_none(w_order):
- order = 'C'
- else:
- order = space.str_w(w_order)
- if order == 'K':
- order = 'C'
- if order != 'C': # or order != 'F':
- raise oefmt(space.w_ValueError, "Unknown order: %s", 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):
@@ -126,7 +121,7 @@
copy = True
if copy:
shape = w_object.get_shape()
- w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order)
+ w_arr = W_NDimArray.from_shape(space, shape, dtype,
order=npy_order)
if support.product(shape) == 1:
w_arr.set_scalar_value(dtype.coerce(space,
w_object.implementation.getitem(0)))
@@ -151,7 +146,7 @@
if dtype is None or (dtype.is_str_or_unicode() and dtype.elsize < 1):
dtype = find_dtype_for_seq(space, elems_w, dtype)
- w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order)
+ w_arr = W_NDimArray.from_shape(space, shape, dtype, order=npy_order)
if support.product(shape) == 1: # safe from overflow since from_shape
checks
w_arr.set_scalar_value(dtype.coerce(space, elems_w[0]))
else:
@@ -268,6 +263,7 @@
def _zeros_or_empty(space, w_shape, w_dtype, w_order, zero):
+ 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))
if dtype.is_str_or_unicode() and dtype.elsize < 1:
@@ -281,7 +277,7 @@
support.product_check(shape)
except OverflowError:
raise oefmt(space.w_ValueError, "array is too big.")
- return W_NDimArray.from_shape(space, shape, dtype=dtype, zero=zero)
+ return W_NDimArray.from_shape(space, shape, dtype, order, zero=zero)
def empty(space, w_shape, w_dtype=None, w_order=None):
return _zeros_or_empty(space, w_shape, w_dtype, w_order, zero=False)
@@ -293,6 +289,7 @@
@unwrap_spec(subok=bool)
def empty_like(space, w_a, w_dtype=None, w_order=None, subok=True):
w_a = convert_to_array(space, w_a)
+ npy_order = order_converter(space, w_order, w_a.get_order())
if space.is_none(w_dtype):
dtype = w_a.get_dtype()
else:
@@ -300,7 +297,16 @@
space.call_function(space.gettypefor(descriptor.W_Dtype), w_dtype))
if dtype.is_str_or_unicode() and dtype.elsize < 1:
dtype = descriptor.variable_dtype(space, dtype.char + '1')
+ if npy_order in (NPY.KEEPORDER, NPY.ANYORDER):
+ # Try to copy the stride pattern
+ impl = w_a.implementation.astype(space, dtype, NPY.KEEPORDER)
+ if subok:
+ w_type = space.type(w_a)
+ else:
+ w_type = None
+ return wrap_impl(space, w_type, w_a, impl)
return W_NDimArray.from_shape(space, w_a.get_shape(), dtype=dtype,
+ order=npy_order,
w_instance=w_a if subok else None,
zero=False)
diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py
--- a/pypy/module/micronumpy/loop.py
+++ b/pypy/module/micronumpy/loop.py
@@ -680,7 +680,7 @@
def tostring(space, arr):
builder = StringBuilder()
iter, state = arr.create_iter()
- w_res_str = W_NDimArray.from_shape(space, [1], arr.get_dtype(), order='C')
+ w_res_str = W_NDimArray.from_shape(space, [1], arr.get_dtype())
itemsize = arr.get_dtype().elsize
with w_res_str.implementation as storage:
res_str_casted = rffi.cast(rffi.CArrayPtr(lltype.Char),
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
@@ -97,11 +97,15 @@
self.fill(space, self.get_dtype().coerce(space, w_value))
def descr_tostring(self, space, w_order=None):
- order = order_converter(space, w_order, NPY.CORDER)
- if order == NPY.FORTRANORDER:
- raise OperationError(space.w_NotImplementedError, space.wrap(
- "unsupported value for order"))
- return space.wrap(loop.tostring(space, self))
+ try:
+ order = order_converter(space, w_order, NPY.CORDER)
+ except:
+ raise oefmt(space.w_TypeError, "order not understood")
+ order = support.get_order_as_CF(self.get_order(), order)
+ arr = self
+ if order != arr.get_order():
+ arr = W_NDimArray(self.implementation.transpose(self, None))
+ return space.wrap(loop.tostring(space, arr))
def getitem_filter(self, space, arr):
if arr.ndims() > 1 and arr.get_shape() != self.get_shape():
@@ -365,11 +369,13 @@
return self.implementation.getitem(self.implementation.start)
def descr_copy(self, space, w_order=None):
- order = order_converter(space, w_order, NPY.KEEPORDER)
- if order == NPY.FORTRANORDER:
- raise OperationError(space.w_NotImplementedError, space.wrap(
- "unsupported value for order"))
- copy = self.implementation.copy(space)
+ if w_order is None:
+ order = NPY.KEEPORDER
+ elif space.isinstance_w(w_order, space.w_int):
+ order = space.int_w(w_order)
+ else:
+ order = order_converter(space, w_order, NPY.KEEPORDER)
+ copy = self.implementation.copy(space, order)
w_subtype = space.type(self)
return wrap_impl(space, w_subtype, self, copy)
@@ -392,15 +398,15 @@
'array does not have imaginary part to set')
self.implementation.set_imag(space, self, w_value)
- def reshape(self, space, w_shape):
+ def reshape(self, space, w_shape, order):
new_shape = get_shape_from_iterable(space, self.get_size(), w_shape)
- new_impl = self.implementation.reshape(self, new_shape)
+ new_impl = self.implementation.reshape(self, new_shape, order)
if new_impl is not None:
return wrap_impl(space, space.type(self), self, new_impl)
# Create copy with contiguous data
- arr = self.descr_copy(space)
+ arr = self.descr_copy(space, space.wrap(order))
if arr.get_size() > 0:
- new_implementation = arr.implementation.reshape(self, new_shape)
+ new_implementation = arr.implementation.reshape(self, new_shape,
order)
if new_implementation is None:
raise oefmt(space.w_ValueError,
'could not reshape array of size %d to shape %s',
@@ -434,16 +440,13 @@
if order == NPY.KEEPORDER:
raise OperationError(space.w_ValueError, space.wrap(
"order 'K' is not permitted for reshaping"))
- if order != NPY.CORDER and order != NPY.ANYORDER:
- raise OperationError(space.w_NotImplementedError, space.wrap(
- "unsupported value for order"))
if len(args_w) == 1:
if space.is_none(args_w[0]):
return self.descr_view(space)
w_shape = args_w[0]
else:
w_shape = space.newtuple(args_w)
- return self.reshape(space, w_shape)
+ return self.reshape(space, w_shape, order)
def descr_get_transpose(self, space, axes=None):
return W_NDimArray(self.implementation.transpose(self, axes))
@@ -514,20 +517,8 @@
return space.newlist(l_w)
def descr_ravel(self, space, w_order=None):
- if space.is_none(w_order):
- order = 'C'
- else:
- order = space.str_w(w_order)
- if order == 'K' and is_c_contiguous(self.implementation):
- for s in self.implementation.get_strides():
- if s < 0:
- break
- else:
- order = 'C'
- if order != 'C':
- raise OperationError(space.w_NotImplementedError, space.wrap(
- "order != 'C' only partially implemented"))
- return self.reshape(space, space.wrap(-1))
+ order = order_converter(space, w_order, self.get_order())
+ return self.reshape(space, space.wrap(-1), order)
@unwrap_spec(w_axis=WrappedDefault(None),
w_out=WrappedDefault(None),
@@ -541,14 +532,15 @@
space.wrap("axis unsupported for compress"))
arr = self
else:
- arr = self.reshape(space, space.wrap(-1))
+ arr = self.reshape(space, space.wrap(-1), self.get_order())
index = convert_to_array(space, w_obj)
return arr.getitem_filter(space, index)
def descr_flatten(self, space, w_order=None):
+ order = order_converter(space, w_order, self.get_order())
if self.is_scalar():
# scalars have no storage
- return self.reshape(space, space.wrap(1))
+ return self.reshape(space, space.wrap(1), order)
w_res = self.descr_ravel(space, w_order)
if w_res.implementation.storage == self.implementation.storage:
return w_res.descr_copy(space)
@@ -631,7 +623,7 @@
space.newtuple([space.wrap(addr),
space.w_False]))
space.setitem_str(w_d, 'shape', self.descr_get_shape(space))
space.setitem_str(w_d, 'typestr',
self.get_dtype().descr_get_str(space))
- if self.implementation.order == 'C':
+ if self.implementation.order == NPY.CORDER:
# Array is contiguous, no strides in the interface.
strides = space.w_None
else:
@@ -690,8 +682,9 @@
"according to the rule %s",
space.str_w(self.get_dtype().descr_repr(space)),
space.str_w(new_dtype.descr_repr(space)), casting)
- order = support.get_order_as_CF(self.get_order(), order)
- if (not copy and new_dtype == self.get_dtype() and order ==
self.get_order()
+ order = order_converter(space, space.wrap(order), self.get_order())
+ if (not copy and new_dtype == self.get_dtype()
+ and (order in (NPY.KEEPORDER, NPY.ANYORDER) or order ==
self.get_order())
and (subok or type(self) is W_NDimArray)):
return self
impl = self.implementation
@@ -972,7 +965,7 @@
raise OperationError(space.w_ValueError, space.wrap(
"new type not compatible with array."))
# Adapt the smallest dim to the new itemsize
- if self.get_order() == 'F':
+ if self.get_order() == NPY.FORTRANORDER:
minstride = strides[0]
mini = 0
else:
@@ -1136,7 +1129,7 @@
matches = True
if dtype != out.get_dtype():
matches = False
- elif not out.implementation.order == "C":
+ elif not out.implementation.order == NPY.CORDER:
matches = False
elif out.ndims() != len(out_shape):
matches = False
@@ -1195,7 +1188,7 @@
out = out_converter(space, w_out)
if space.is_none(w_axis):
w_axis = space.wrap(0)
- arr = self.reshape(space, space.wrap(-1))
+ arr = self.reshape(space, space.wrap(-1), self.get_order())
else:
arr = self
ufunc = getattr(ufuncs.get(space), ufunc_name)
@@ -1408,10 +1401,6 @@
strides=strides)
order = order_converter(space, w_order, NPY.CORDER)
- if order == NPY.CORDER:
- order = 'C'
- else:
- order = 'F'
if space.is_w(w_subtype, space.gettypefor(W_NDimArray)):
return W_NDimArray.from_shape(space, shape, dtype, order)
strides, backstrides = calc_strides(shape, dtype.base, order)
@@ -1448,7 +1437,7 @@
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,
- buf_len, 'C', False,
w_subtype,
+ buf_len, NPY.CORDER, False,
w_subtype,
strides=strides)
else:
return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype,
diff --git a/pypy/module/micronumpy/nditer.py b/pypy/module/micronumpy/nditer.py
--- a/pypy/module/micronumpy/nditer.py
+++ b/pypy/module/micronumpy/nditer.py
@@ -11,6 +11,8 @@
shape_agreement,
shape_agreement_multiple)
from pypy.module.micronumpy.casting import (find_binop_result_dtype,
can_cast_array, can_cast_type)
+import pypy.module.micronumpy.constants as NPY
+from pypy.module.micronumpy.converters import order_converter
def parse_op_arg(space, name, w_op_flags, n, parse_one_arg):
@@ -142,14 +144,13 @@
'Iterator flag EXTERNAL_LOOP cannot be used if an index or '
'multi-index is being tracked')
-
-def is_backward(imp, order):
- if order == 'K' or (order == 'C' and imp.order == 'C'):
+def is_backward(imp_order, order):
+ if imp_order == order:
return False
- elif order == 'F' and imp.order == 'C':
+ if order == NPY.KEEPORDER:
+ return False
+ else:
return True
- else:
- raise NotImplementedError('not implemented yet')
class OperandIter(ArrayIter):
@@ -234,7 +235,7 @@
continue
assert isinstance(op_it, ArrayIter)
indx = len(op_it.strides)
- if it.order == 'F':
+ if it.order == NPY.FORTRANORDER:
indx = len(op_it.array.strides) - indx
assert indx >=0
astrides = op_it.array.strides[indx:]
@@ -250,7 +251,7 @@
it.order)
it.iters[i] = (new_iter, new_iter.reset())
if len(it.shape) > 1:
- if it.order == 'F':
+ if it.order == NPY.FORTRANORDER:
it.shape = it.shape[1:]
else:
it.shape = it.shape[:-1]
@@ -261,10 +262,10 @@
break
# Always coalesce at least one
for i in range(len(it.iters)):
- new_iter = coalesce_iter(it.iters[i][0], it.op_flags[i], it, 'C')
+ new_iter = coalesce_iter(it.iters[i][0], it.op_flags[i], it,
NPY.CORDER)
it.iters[i] = (new_iter, new_iter.reset())
if len(it.shape) > 1:
- if it.order == 'F':
+ if it.order == NPY.FORTRANORDER:
it.shape = it.shape[1:]
else:
it.shape = it.shape[:-1]
@@ -287,7 +288,7 @@
return old_iter
strides = old_iter.strides
backstrides = old_iter.backstrides
- if order == 'F':
+ if order == NPY.FORTRANORDER:
new_shape = shape[1:]
new_strides = strides[1:]
new_backstrides = backstrides[1:]
@@ -346,8 +347,8 @@
class W_NDIter(W_NumpyObject):
_immutable_fields_ = ['ndim', ]
def __init__(self, space, w_seq, w_flags, w_op_flags, w_op_dtypes,
- w_casting, w_op_axes, w_itershape, buffersize=0, order='K'):
- self.order = order
+ w_casting, w_op_axes, w_itershape, buffersize=0,
+ order=NPY.KEEPORDER):
self.external_loop = False
self.buffered = False
self.tracked_index = ''
@@ -375,7 +376,25 @@
for w_elem in w_seq_as_list]
else:
self.seq = [convert_to_array(space, w_seq)]
-
+ if order == NPY.ANYORDER:
+ # 'A' means "'F' order if all the arrays are Fortran contiguous,
+ # 'C' order otherwise"
+ order = NPY.CORDER
+ for s in self.seq:
+ if s and not(s.get_flags() & NPY.ARRAY_F_CONTIGUOUS):
+ break
+ else:
+ order = NPY.FORTRANORDER
+ elif order == NPY.KEEPORDER:
+ # 'K' means "as close to the order the array elements appear in
+ # memory as possible", so match self.order to seq.order
+ order = NPY.CORDER
+ for s in self.seq:
+ if s and not(s.get_order() == NPY.FORTRANORDER):
+ break
+ else:
+ order = NPY.FORTRANORDER
+ self.order = order
parse_func_flags(space, self, w_flags)
self.op_flags = parse_op_arg(space, 'op_flags', w_op_flags,
len(self.seq), parse_op_flag)
@@ -439,12 +458,15 @@
str(self.shape))
if self.tracked_index != "":
- if self.order == "K":
- self.order = self.seq[0].implementation.order
+ order = self.order
+ if order == NPY.KEEPORDER:
+ order = self.seq[0].implementation.order
if self.tracked_index == "multi":
backward = False
else:
- backward = self.order != self.tracked_index
+ backward = ((
+ order == NPY.CORDER and self.tracked_index != 'C') or (
+ order == NPY.FORTRANORDER and self.tracked_index != 'F'))
self.index_iter = IndexIterator(self.shape, backward=backward)
# handle w_op_dtypes part 2: copy where needed if possible
@@ -456,7 +478,6 @@
self.dtypes[i] = seq_d
elif self_d != seq_d:
impl = self.seq[i].implementation
- order = support.get_order_as_CF(impl.order, self.order)
if self.buffered or 'r' in self.op_flags[i].tmp_copy:
if not can_cast_array(
space, self.seq[i], self_d, self.casting):
@@ -466,7 +487,7 @@
space.str_w(seq_d.descr_repr(space)),
space.str_w(self_d.descr_repr(space)),
self.casting)
-
+ order = support.get_order_as_CF(impl.order,
self.order)
new_impl = impl.astype(space, self_d,
order).copy(space)
self.seq[i] = W_NDimArray(new_impl)
else:
@@ -484,7 +505,7 @@
space.str_w(self_d.descr_repr(space)),
space.str_w(seq_d.descr_repr(space)),
i, self.casting)
- elif self.buffered:
+ elif self.buffered and not (self.external_loop and len(self.seq)<2):
for i in range(len(self.seq)):
if i not in outargs:
self.seq[i] = self.seq[i].descr_copy(space,
@@ -506,12 +527,19 @@
def get_iter(self, space, i):
arr = self.seq[i]
- dtype = self.dtypes[i]
- shape = self.shape
imp = arr.implementation
- backward = is_backward(imp, self.order)
if arr.is_scalar():
return ConcreteIter(imp, 1, [], [], [], self.op_flags[i], self)
+ shape = self.shape
+ if (self.external_loop and len(self.seq)<2 and self.buffered):
+ # Special case, always return a memory-ordered iterator
+ stride = imp.dtype.elsize
+ backstride = imp.size * stride - stride
+ return ConcreteIter(imp, imp.get_size(),
+ [support.product(shape)], [stride], [backstride],
+ self.op_flags[i], self)
+ backward = imp.order != self.order
+ # XXX cleanup needed
if (abs(imp.strides[0]) < abs(imp.strides[-1]) and not backward) or \
(abs(imp.strides[0]) > abs(imp.strides[-1]) and backward):
# flip the strides. Is this always true for multidimension?
@@ -704,13 +732,15 @@
@unwrap_spec(w_flags=WrappedDefault(None), w_op_flags=WrappedDefault(None),
- w_op_dtypes=WrappedDefault(None), order=str,
+ w_op_dtypes=WrappedDefault(None), w_order=WrappedDefault(None),
w_casting=WrappedDefault(None), w_op_axes=WrappedDefault(None),
- w_itershape=WrappedDefault(None), buffersize=int)
+ w_itershape=WrappedDefault(None), w_buffersize=WrappedDefault(0))
def descr_new_nditer(space, w_subtype, w_seq, w_flags, w_op_flags, w_op_dtypes,
- w_casting, w_op_axes, w_itershape, buffersize=0, order='K'):
+ w_casting, w_op_axes, w_itershape, w_buffersize, w_order):
+ npy_order = order_converter(space, w_order, NPY.KEEPORDER)
+ buffersize = space.int_w(w_buffersize)
return W_NDIter(space, w_seq, w_flags, w_op_flags, w_op_dtypes, w_casting,
w_op_axes,
- w_itershape, buffersize, order)
+ w_itershape, buffersize, npy_order)
W_NDIter.typedef = TypeDef('numpy.nditer',
__new__ = interp2app(descr_new_nditer),
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
@@ -310,14 +310,14 @@
backstrides = []
s = 1
shape_rev = shape[:]
- if order == 'C':
+ if order in [NPY.CORDER, NPY.ANYORDER]:
shape_rev.reverse()
for sh in shape_rev:
slimit = max(sh, 1)
strides.append(s * dtype.elsize)
backstrides.append(s * (slimit - 1) * dtype.elsize)
s *= slimit
- if order == 'C':
+ if order in [NPY.CORDER, NPY.ANYORDER]:
strides.reverse()
backstrides.reverse()
return strides, backstrides
@@ -345,7 +345,7 @@
last_step = 1
oldI = 0
new_strides = []
- if order == 'F':
+ if order == NPY.FORTRANORDER:
for i in range(len(old_shape)):
steps.append(old_strides[i] / last_step)
last_step *= old_shape[i]
@@ -365,7 +365,7 @@
if oldI < len(old_shape):
cur_step = steps[oldI]
n_old_elems_to_use *= old_shape[oldI]
- elif order == 'C':
+ else:
for i in range(len(old_shape) - 1, -1, -1):
steps.insert(0, old_strides[i] / last_step)
last_step *= old_shape[i]
diff --git a/pypy/module/micronumpy/support.py
b/pypy/module/micronumpy/support.py
--- a/pypy/module/micronumpy/support.py
+++ b/pypy/module/micronumpy/support.py
@@ -7,6 +7,7 @@
from pypy.interpreter.typedef import GetSetProperty
from pypy.objspace.std.typeobject import W_TypeObject
from pypy.objspace.std.objspace import StdObjSpace
+from pypy.module.micronumpy import constants as NPY
def issequence_w(space, w_obj):
from pypy.module.micronumpy.base import W_NDimArray
@@ -176,15 +177,11 @@
return space.is_true(space.gt(w_priority_r, w_priority_l))
def get_order_as_CF(proto_order, req_order):
- if req_order == 'C':
- return 'C'
- elif req_order == 'F':
- return 'F'
- elif req_order == 'K':
- return proto_order
- elif req_order == 'A':
- return proto_order
-
+ if req_order == NPY.CORDER:
+ return NPY.CORDER
+ elif req_order == NPY.FORTRANORDER:
+ return NPY.FORTRANORDER
+ return proto_order
def descr_set_docstring(space, w_obj, w_docstring):
if not isinstance(space, StdObjSpace):
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
@@ -6,6 +6,7 @@
from pypy.module.micronumpy.appbridge import get_appbridge_cache
from pypy.module.micronumpy.strides import Chunk, new_view, EllipsisChunk
from pypy.module.micronumpy.ndarray import W_NDimArray
+import pypy.module.micronumpy.constants as NPY
from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
@@ -45,20 +46,20 @@
return self.space.newtuple(args_w)
def test_strides_f(self):
- a = create_array(self.space, [10, 5, 3], MockDtype(), order='F')
+ a = create_array(self.space, [10, 5, 3], MockDtype(),
order=NPY.FORTRANORDER)
assert a.strides == [1, 10, 50]
assert a.backstrides == [9, 40, 100]
def test_strides_c(self):
- a = create_array(self.space, [10, 5, 3], MockDtype(), order='C')
+ a = create_array(self.space, [10, 5, 3], MockDtype(), order=NPY.CORDER)
assert a.strides == [15, 3, 1]
assert a.backstrides == [135, 12, 2]
- a = create_array(self.space, [1, 0, 7], MockDtype(), order='C')
+ a = create_array(self.space, [1, 0, 7], MockDtype(), order=NPY.CORDER)
assert a.strides == [7, 7, 1]
assert a.backstrides == [0, 0, 6]
def test_create_slice_f(self):
- a = create_array(self.space, [10, 5, 3], MockDtype(), order='F')
+ a = create_array(self.space, [10, 5, 3], MockDtype(),
order=NPY.FORTRANORDER)
s = create_slice(self.space, a, [Chunk(3, 0, 0, 1)])
assert s.start == 3
assert s.strides == [10, 50]
@@ -77,7 +78,7 @@
assert s.shape == [10, 3]
def test_create_slice_c(self):
- a = create_array(self.space, [10, 5, 3], MockDtype(), order='C')
+ a = create_array(self.space, [10, 5, 3], MockDtype(), order=NPY.CORDER)
s = create_slice(self.space, a, [Chunk(3, 0, 0, 1)])
assert s.start == 45
assert s.strides == [3, 1]
@@ -97,7 +98,7 @@
assert s.shape == [10, 3]
def test_slice_of_slice_f(self):
- a = create_array(self.space, [10, 5, 3], MockDtype(), order='F')
+ a = create_array(self.space, [10, 5, 3], MockDtype(),
order=NPY.FORTRANORDER)
s = create_slice(self.space, a, [Chunk(5, 0, 0, 1)])
assert s.start == 5
s2 = create_slice(self.space, s, [Chunk(3, 0, 0, 1)])
@@ -114,7 +115,7 @@
assert s2.start == 1 * 15 + 2 * 3
def test_slice_of_slice_c(self):
- a = create_array(self.space, [10, 5, 3], MockDtype(), order='C')
+ a = create_array(self.space, [10, 5, 3], MockDtype(), order=NPY.CORDER)
s = create_slice(self.space, a, [Chunk(5, 0, 0, 1)])
assert s.start == 15 * 5
s2 = create_slice(self.space, s, [Chunk(3, 0, 0, 1)])
@@ -131,14 +132,14 @@
assert s2.start == 1 * 15 + 2 * 3
def test_negative_step_f(self):
- a = create_array(self.space, [10, 5, 3], MockDtype(), order='F')
+ a = create_array(self.space, [10, 5, 3], MockDtype(),
order=NPY.FORTRANORDER)
s = create_slice(self.space, a, [Chunk(9, -1, -2, 5)])
assert s.start == 9
assert s.strides == [-2, 10, 50]
assert s.backstrides == [-8, 40, 100]
def test_negative_step_c(self):
- a = create_array(self.space, [10, 5, 3], MockDtype(), order='C')
+ a = create_array(self.space, [10, 5, 3], MockDtype(), order=NPY.CORDER)
s = create_slice(self.space, a, [Chunk(9, -1, -2, 5)])
assert s.start == 135
assert s.strides == [-30, 3, 1]
@@ -155,17 +156,17 @@
def test_calc_new_strides(self):
from pypy.module.micronumpy.strides import calc_new_strides
- assert calc_new_strides([2, 4], [4, 2], [4, 2], "C") == [8, 2]
- assert calc_new_strides([2, 4, 3], [8, 3], [1, 16], 'F') == [1, 2, 16]
- assert calc_new_strides([2, 3, 4], [8, 3], [1, 16], 'F') is None
- assert calc_new_strides([24], [2, 4, 3], [48, 6, 1], 'C') is None
- assert calc_new_strides([24], [2, 4, 3], [24, 6, 2], 'C') == [2]
- assert calc_new_strides([105, 1], [3, 5, 7], [35, 7, 1],'C') == [1, 1]
- assert calc_new_strides([1, 105], [3, 5, 7], [35, 7, 1],'C') == [105,
1]
- assert calc_new_strides([1, 105], [3, 5, 7], [35, 7, 1],'F') is None
- assert calc_new_strides([1, 1, 1, 105, 1], [15, 7], [7, 1],'C') == \
+ assert calc_new_strides([2, 4], [4, 2], [4, 2], NPY.CORDER) == [8, 2]
+ assert calc_new_strides([2, 4, 3], [8, 3], [1, 16], NPY.FORTRANORDER)
== [1, 2, 16]
+ assert calc_new_strides([2, 3, 4], [8, 3], [1, 16], NPY.FORTRANORDER)
is None
+ assert calc_new_strides([24], [2, 4, 3], [48, 6, 1], NPY.CORDER) is
None
+ assert calc_new_strides([24], [2, 4, 3], [24, 6, 2], NPY.CORDER) == [2]
+ assert calc_new_strides([105, 1], [3, 5, 7], [35, 7, 1],NPY.CORDER) ==
[1, 1]
+ assert calc_new_strides([1, 105], [3, 5, 7], [35, 7, 1],NPY.CORDER) ==
[105, 1]
+ assert calc_new_strides([1, 105], [3, 5, 7], [35, 7,
1],NPY.FORTRANORDER) is None
+ assert calc_new_strides([1, 1, 1, 105, 1], [15, 7], [7, 1],NPY.CORDER)
== \
[105, 105, 105, 1, 1]
- assert calc_new_strides([1, 1, 105, 1, 1], [7, 15], [1, 7],'F') == \
+ assert calc_new_strides([1, 1, 105, 1, 1], [7, 15], [1,
7],NPY.FORTRANORDER) == \
[1, 1, 1, 105, 105]
def test_find_shape(self):
@@ -444,6 +445,8 @@
b = np.empty_like(A((2, 3)), subok=False)
assert b.shape == (2, 3)
assert type(b) is np.ndarray
+ b = np.empty_like(np.array(3.0), order='A')
+ assert type(b) is np.ndarray
def test_size(self):
from numpy import array,arange,cos
@@ -534,10 +537,10 @@
assert (b == a).all()
b = a.copy(order='A')
assert (b == a).all()
- import sys
- if '__pypy__' in sys.builtin_module_names:
- raises(NotImplementedError, a.copy, order='F')
- raises(NotImplementedError, a.copy, order=True)
+ b = a.copy(order='F')
+ assert (b == a).all()
+ b = a.copy(order=True)
+ assert (b == a).all()
def test_iterator_init(self):
from numpy import array
@@ -918,9 +921,11 @@
assert a.reshape((0,), order='A').shape == (0,)
raises(TypeError, a.reshape, (0,), badarg="C")
raises(ValueError, a.reshape, (0,), order="K")
- import sys
- if '__pypy__' in sys.builtin_module_names:
- raises(NotImplementedError, a.reshape, (0,), order='F')
+ b = a.reshape((0,), order='F')
+ assert b.shape == (0,)
+ a = array(range(24), 'uint8')
+ assert a.reshape([2, 3, 4], order=True).strides ==(1, 2, 6)
+ assert a.reshape([2, 3, 4], order=False).strides ==(12, 4, 1)
def test_slice_reshape(self):
from numpy import zeros, arange
@@ -2676,11 +2681,11 @@
assert a[1][2][1] == 15
def test_create_order(self):
- import sys, numpy as np
+ import numpy as np
for order in [False, True, 'C', 'F']:
a = np.empty((2, 3), float, order=order)
assert a.shape == (2, 3)
- if order in [True, 'F'] and '__pypy__' not in
sys.builtin_module_names:
+ if order in [True, 'F']:
assert a.flags['F']
assert not a.flags['C']
else:
@@ -3577,10 +3582,7 @@
assert a.tostring(order) == '\x01\x02\x03\x04'
import sys
for order in (True, 'F'):
- if '__pypy__' in sys.builtin_module_names:
- raises(NotImplementedError, a.tostring, order)
- else:
- assert a.tostring(order) == '\x01\x03\x02\x04'
+ assert a.tostring(order) == '\x01\x03\x02\x04'
assert array(2.2-1.1j, dtype='>c16').tostring() == \
'@\x01\x99\x99\x99\x99\x99\x9a\xbf\xf1\x99\x99\x99\x99\x99\x9a'
assert array(2.2-1.1j, dtype='<c16').tostring() == \
diff --git a/pypy/module/micronumpy/test/test_nditer.py
b/pypy/module/micronumpy/test/test_nditer.py
--- a/pypy/module/micronumpy/test/test_nditer.py
+++ b/pypy/module/micronumpy/test/test_nditer.py
@@ -114,14 +114,11 @@
from numpy import nditer, array
a = array([[1, 2], [3, 4]], order="C")
- try:
- b = array([[1, 2], [3, 4]], order="F")
- except (NotImplementedError, ValueError):
- skip('Fortran order not implemented')
+ b = array([[1, 2], [3, 4]], order="F")
it = nditer([a, b])
-
- assert list(it) == zip(range(1, 5), range(1, 5))
+ r = list(it)
+ assert r == zip(range(1, 5), range(1, 5))
def test_interface(self):
from numpy import arange, nditer, zeros
@@ -161,11 +158,7 @@
assert r[0][0] == 100
r = []
- try:
- it = nditer(a, flags=['buffered'], order='F')
- except NotImplementedError as e:
- assert 'unsupported value for order' in str(e)
- skip('buffered with order="F" requires fortran tmp array creation')
+ it = nditer(a, flags=['buffered'], order='F')
for x in it:
r.append(x)
array_r = array(r)
diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py
--- a/pypy/module/micronumpy/ufuncs.py
+++ b/pypy/module/micronumpy/ufuncs.py
@@ -668,9 +668,9 @@
for dt_in, dt_out in self.dtypes:
if can_cast_to(dtype, dt_in) and dt_out == dt_in:
return dt_in
- raise ValueError(
+ raise oefmt(space.w_ValueError,
"could not find a matching type for %s.accumulate, "
- "requested type has type code '%s'" % (self.name, dtype.char))
+ "requested type has type code '%s'", self.name, dtype.char)
@jit.unroll_safe
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit