summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/release/1.8.0-notes.rst18
-rw-r--r--doc/source/reference/c-api.types-and-structures.rst10
-rw-r--r--numpy/core/include/numpy/ufuncobject.h14
-rw-r--r--numpy/core/setup.py7
-rw-r--r--numpy/core/src/multiarray/arraytypes.c.src2
-rw-r--r--numpy/core/src/umath/operand_flag_tests.c.src106
-rw-r--r--numpy/core/src/umath/ufunc_object.c92
-rw-r--r--numpy/core/src/umath/umathmodule.c6
-rw-r--r--numpy/core/tests/test_api.py8
-rw-r--r--numpy/core/tests/test_regression.py5
-rw-r--r--numpy/core/tests/test_ufunc.py14
-rw-r--r--numpy/lib/arraypad.py190
-rw-r--r--numpy/lib/stride_tricks.py5
-rw-r--r--numpy/testing/nosetester.py8
14 files changed, 371 insertions, 114 deletions
diff --git a/doc/release/1.8.0-notes.rst b/doc/release/1.8.0-notes.rst
index c5c9d6e8d..e65658ad3 100644
--- a/doc/release/1.8.0-notes.rst
+++ b/doc/release/1.8.0-notes.rst
@@ -159,3 +159,21 @@ General
Use of non-integer indices has been deprecated. Previously float indices
were truncated to integers without warning.
+C-API
+~~~~~
+
+New Features
+============
+
+When creating a ufunc, the default ufunc operand flags can be overridden
+via the new op_flags attribute of the ufunc object. For example, to set
+the operand flag for the first input to read/write:
+
+PyObject \*ufunc = PyUFunc_FromFuncAndData(...);
+ufunc->op_flags[0] = NPY_ITER_READWRITE;
+
+This allows a ufunc to perform an operation in place. Also, global nditer flags
+can be overridden via the new iter_flags attribute of the ufunc object.
+For example, to set the reduce flag for a ufunc:
+
+ufunc->iter_flags = NPY_ITER_REDUCE_OK;
diff --git a/doc/source/reference/c-api.types-and-structures.rst b/doc/source/reference/c-api.types-and-structures.rst
index 07c7e07be..79a888912 100644
--- a/doc/source/reference/c-api.types-and-structures.rst
+++ b/doc/source/reference/c-api.types-and-structures.rst
@@ -652,6 +652,8 @@ PyUFunc_Type
void *ptr;
PyObject *obj;
PyObject *userloops;
+ npy_uint32 *op_flags;
+ npy_uint32 *iter_flags;
} PyUFuncObject;
.. cmacro:: PyUFuncObject.PyObject_HEAD
@@ -755,6 +757,14 @@ PyUFunc_Type
numbers are always larger than :cdata:`NPY_USERDEF`.
+ .. cmember:: npy_uint32 PyUFuncObject.op_flags
+
+ Override the default operand flags for each ufunc operand.
+
+ .. cmember:: npy_uint32 PyUFuncObject.iter_flags
+
+ Override the default nditer flags for the ufunc.
+
PyArrayIter_Type
----------------
diff --git a/numpy/core/include/numpy/ufuncobject.h b/numpy/core/include/numpy/ufuncobject.h
index 076dd880c..686d12c38 100644
--- a/numpy/core/include/numpy/ufuncobject.h
+++ b/numpy/core/include/numpy/ufuncobject.h
@@ -212,6 +212,20 @@ typedef struct _tagPyUFuncObject {
* A function which returns a masked inner loop for the ufunc.
*/
PyUFunc_MaskedInnerLoopSelectionFunc *masked_inner_loop_selector;
+
+ /*
+ * List of flags for each operand when ufunc is called by nditer object.
+ * These flags will be used in addition to the default flags for each
+ * operand set by nditer object.
+ */
+ npy_uint32 *op_flags;
+
+ /*
+ * List of global flags used when ufunc is called by nditer object.
+ * These flags will be used in addition to the default global flags
+ * set by nditer object.
+ */
+ npy_uint32 iter_flags;
} PyUFuncObject;
#include "arrayobject.h"
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index 6df82b3fa..3b08d6edd 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -935,6 +935,13 @@ def configuration(parent_package='',top_path=None):
config.add_extension('multiarray_tests',
sources = [join('src', 'multiarray', 'multiarray_tests.c.src')])
+ #######################################################################
+ # operand_flag_tests module #
+ #######################################################################
+
+ config.add_extension('operand_flag_tests',
+ sources = [join('src','umath', 'operand_flag_tests.c.src')])
+
config.add_data_dir('tests')
config.add_data_dir('tests/data')
diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src
index aff4c36dd..4a5c13a6a 100644
--- a/numpy/core/src/multiarray/arraytypes.c.src
+++ b/numpy/core/src/multiarray/arraytypes.c.src
@@ -2321,7 +2321,7 @@ VOID_nonzero (char *ip, PyArrayObject *ap)
* TODO: temporarily modifying the array like this
* is bad coding style, should be changed.
*/
- ((PyArrayObject_fields *)ap)->descr = descr;
+ ((PyArrayObject_fields *)ap)->descr = new;
((PyArrayObject_fields *)ap)->flags = savedflags;
if ((new->alignment > 1) && !__ALIGNED(ip + offset,
new->alignment)) {
diff --git a/numpy/core/src/umath/operand_flag_tests.c.src b/numpy/core/src/umath/operand_flag_tests.c.src
new file mode 100644
index 000000000..0cae4db36
--- /dev/null
+++ b/numpy/core/src/umath/operand_flag_tests.c.src
@@ -0,0 +1,106 @@
+#define NPY_NO_DEPRECATED_API NPY_API_VERSION
+
+#include <stdint.h>
+#include <math.h>
+#include <Python.h>
+#include <structmember.h>
+#include <numpy/arrayobject.h>
+#include <numpy/ufuncobject.h>
+#include "numpy/npy_3kcompat.h"
+
+
+static PyMethodDef TestMethods[] = {
+ {NULL, NULL, 0, NULL}
+};
+
+
+static void
+inplace_add(char **args, npy_intp *dimensions, npy_intp *steps, void *data)
+{
+ npy_intp i;
+ npy_intp n = dimensions[0];
+ char *in1 = args[0];
+ char *in2 = args[1];
+ npy_intp in1_step = steps[0];
+ npy_intp in2_step = steps[1];
+
+ for (i = 0; i < n; i++) {
+ (*(long *)in1) = *(long*)in1 + *(long*)in2;
+ in1 += in1_step;
+ in2 += in2_step;
+ }
+}
+
+
+/*This a pointer to the above function*/
+PyUFuncGenericFunction funcs[1] = {&inplace_add};
+
+/* These are the input and return dtypes of logit.*/
+static char types[2] = {NPY_LONG, NPY_LONG};
+
+static void *data[1] = {NULL};
+
+#if defined(NPY_PY3K)
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "operand_flag_tests",
+ NULL,
+ -1,
+ TestMethods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+#define RETVAL m
+PyMODINIT_FUNC PyInit_operand_flag_tests(void)
+{
+#else
+#define RETVAL
+PyMODINIT_FUNC initoperand_flag_tests(void)
+{
+#endif
+ PyObject *m = NULL;
+ PyObject *ufunc;
+
+#if defined(NPY_PY3K)
+ m = PyModule_Create(&moduledef);
+#else
+ m = Py_InitModule("operand_flag_tests", TestMethods);
+#endif
+ if (m == NULL) {
+ goto fail;
+ }
+
+ import_array();
+ import_umath();
+
+ ufunc = PyUFunc_FromFuncAndData(funcs, data, types, 1, 2, 0,
+ PyUFunc_None, "inplace_add",
+ "inplace_add_docstring", 0);
+
+ /*
+ * Set flags to turn off buffering for first input operand,
+ * so that result can be written back to input operand.
+ */
+ ((PyUFuncObject*)ufunc)->op_flags[0] = NPY_ITER_READWRITE;
+ ((PyUFuncObject*)ufunc)->iter_flags = NPY_ITER_REDUCE_OK;
+ PyModule_AddObject(m, "inplace_add", (PyObject*)ufunc);
+
+ return RETVAL;
+
+fail:
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "cannot load operand_flag_tests module.");
+ }
+#if defined(NPY_PY3K)
+ if (m) {
+ Py_DECREF(m);
+ m = NULL;
+ }
+#endif
+ return RETVAL;
+
+}
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 3d3f63d4e..a3a164731 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -1181,34 +1181,46 @@ iterator_loop(PyUFuncObject *ufunc,
npy_intp *count_ptr;
PyArrayObject **op_it;
+ npy_uint32 iter_flags;
NPY_BEGIN_THREADS_DEF;
/* Set up the flags */
for (i = 0; i < nin; ++i) {
- op_flags[i] = NPY_ITER_READONLY|
+ op_flags[i] = NPY_ITER_READONLY |
NPY_ITER_ALIGNED;
+ /*
+ * If READWRITE flag has been set for this operand,
+ * then clear default READONLY flag
+ */
+ op_flags[i] |= ufunc->op_flags[i];
+ if (op_flags[i] & (NPY_ITER_READWRITE | NPY_ITER_WRITEONLY)) {
+ op_flags[i] &= ~NPY_ITER_READONLY;
+ }
}
for (i = nin; i < nop; ++i) {
- op_flags[i] = NPY_ITER_WRITEONLY|
- NPY_ITER_ALIGNED|
- NPY_ITER_ALLOCATE|
- NPY_ITER_NO_BROADCAST|
+ op_flags[i] = NPY_ITER_WRITEONLY |
+ NPY_ITER_ALIGNED |
+ NPY_ITER_ALLOCATE |
+ NPY_ITER_NO_BROADCAST |
NPY_ITER_NO_SUBTYPE;
}
+ iter_flags = ufunc->iter_flags |
+ NPY_ITER_EXTERNAL_LOOP |
+ NPY_ITER_REFS_OK |
+ NPY_ITER_ZEROSIZE_OK |
+ NPY_ITER_BUFFERED |
+ NPY_ITER_GROWINNER |
+ NPY_ITER_DELAY_BUFALLOC;
+
/*
* Allocate the iterator. Because the types of the inputs
* were already checked, we use the casting rule 'unsafe' which
* is faster to calculate.
*/
iter = NpyIter_AdvancedNew(nop, op,
- NPY_ITER_EXTERNAL_LOOP|
- NPY_ITER_REFS_OK|
- NPY_ITER_ZEROSIZE_OK|
- NPY_ITER_BUFFERED|
- NPY_ITER_GROWINNER|
- NPY_ITER_DELAY_BUFALLOC,
+ iter_flags,
order, NPY_UNSAFE_CASTING,
op_flags, dtype,
-1, NULL, NULL, buffersize);
@@ -1462,6 +1474,7 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
npy_intp *countptr;
PyArrayObject **op_it;
+ npy_uint32 iter_flags;
NPY_BEGIN_THREADS_DEF;
@@ -1481,6 +1494,14 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
op_flags[i] = default_op_in_flags |
NPY_ITER_READONLY |
NPY_ITER_ALIGNED;
+ /*
+ * If READWRITE flag has been set for this operand,
+ * then clear default READONLY flag
+ */
+ op_flags[i] |= ufunc->op_flags[i];
+ if (op_flags[i] & (NPY_ITER_READWRITE | NPY_ITER_WRITEONLY)) {
+ op_flags[i] &= ~NPY_ITER_READONLY;
+ }
}
for (i = nin; i < nop; ++i) {
op_flags[i] = default_op_out_flags |
@@ -1496,17 +1517,20 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
NPY_UF_DBG_PRINT("Making iterator\n");
+ iter_flags = ufunc->iter_flags |
+ NPY_ITER_EXTERNAL_LOOP |
+ NPY_ITER_REFS_OK |
+ NPY_ITER_ZEROSIZE_OK |
+ NPY_ITER_BUFFERED |
+ NPY_ITER_GROWINNER;
+
/*
* Allocate the iterator. Because the types of the inputs
* were already checked, we use the casting rule 'unsafe' which
* is faster to calculate.
*/
iter = NpyIter_AdvancedNew(nop + ((wheremask != NULL) ? 1 : 0), op,
- NPY_ITER_EXTERNAL_LOOP |
- NPY_ITER_REFS_OK |
- NPY_ITER_ZEROSIZE_OK |
- NPY_ITER_BUFFERED |
- NPY_ITER_GROWINNER,
+ iter_flags,
order, NPY_UNSAFE_CASTING,
op_flags, dtypes,
-1, NULL, NULL, buffersize);
@@ -1663,8 +1687,8 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
npy_uint32 op_flags[NPY_MAXARGS];
npy_intp iter_shape[NPY_MAXARGS];
-
NpyIter *iter = NULL;
+ npy_uint32 iter_flags;
/* These parameters come from extobj= or from a TLS global */
int buffersize = 0, errormask = 0;
@@ -1964,9 +1988,17 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
* can't do buffering, so must COPY or UPDATEIFCOPY.
*/
for (i = 0; i < nin; ++i) {
- op_flags[i] = NPY_ITER_READONLY|
- NPY_ITER_COPY|
+ op_flags[i] = NPY_ITER_READONLY |
+ NPY_ITER_COPY |
NPY_ITER_ALIGNED;
+ /*
+ * If READWRITE flag has been set for this operand,
+ * then clear default READONLY flag
+ */
+ op_flags[i] |= ufunc->op_flags[i];
+ if (op_flags[i] & (NPY_ITER_READWRITE | NPY_ITER_WRITEONLY)) {
+ op_flags[i] &= ~NPY_ITER_READONLY;
+ }
}
for (i = nin; i < nop; ++i) {
op_flags[i] = NPY_ITER_READWRITE|
@@ -1976,11 +2008,14 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
NPY_ITER_NO_BROADCAST;
}
+ iter_flags = ufunc->iter_flags |
+ NPY_ITER_MULTI_INDEX |
+ NPY_ITER_REFS_OK |
+ NPY_ITER_REDUCE_OK |
+ NPY_ITER_ZEROSIZE_OK;
+
/* Create the iterator */
- iter = NpyIter_AdvancedNew(nop, op, NPY_ITER_MULTI_INDEX|
- NPY_ITER_REFS_OK|
- NPY_ITER_REDUCE_OK|
- NPY_ITER_ZEROSIZE_OK,
+ iter = NpyIter_AdvancedNew(nop, op, iter_flags,
order, NPY_UNSAFE_CASTING, op_flags,
dtypes, iter_ndim,
op_axes, iter_shape, 0);
@@ -4227,6 +4262,14 @@ PyUFunc_FromFuncAndDataAndSignature(PyUFuncGenericFunction *func, void **data,
}
ufunc->doc = doc;
+ ufunc->op_flags = PyArray_malloc(sizeof(npy_uint32)*ufunc->nargs);
+ if (ufunc->op_flags == NULL) {
+ return PyErr_NoMemory();
+ }
+ memset(ufunc->op_flags, 0, sizeof(npy_uint32)*ufunc->nargs);
+
+ ufunc->iter_flags = 0;
+
/* generalized ufunc */
ufunc->core_enabled = 0;
ufunc->core_num_dim_ix = 0;
@@ -4476,6 +4519,9 @@ ufunc_dealloc(PyUFuncObject *ufunc)
if (ufunc->ptr) {
PyArray_free(ufunc->ptr);
}
+ if (ufunc->op_flags) {
+ PyArray_free(ufunc->op_flags);
+ }
Py_XDECREF(ufunc->userloops);
Py_XDECREF(ufunc->obj);
PyArray_free(ufunc);
diff --git a/numpy/core/src/umath/umathmodule.c b/numpy/core/src/umath/umathmodule.c
index e06cdedd1..0b789de26 100644
--- a/numpy/core/src/umath/umathmodule.c
+++ b/numpy/core/src/umath/umathmodule.c
@@ -123,6 +123,12 @@ ufunc_frompyfunc(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *NPY_UNUS
self->core_dim_ixs = NULL;
self->core_offsets = NULL;
self->core_signature = NULL;
+ self->op_flags = PyArray_malloc(sizeof(npy_uint32)*self->nargs);
+ if (self->op_flags == NULL) {
+ return PyErr_NoMemory();
+ }
+ memset(self->op_flags, 0, sizeof(npy_uint32)*self->nargs);
+ self->iter_flags = 0;
self->type_resolver = &object_ufunc_type_resolver;
self->legacy_inner_loop_selector = &object_ufunc_loop_selector;
diff --git a/numpy/core/tests/test_api.py b/numpy/core/tests/test_api.py
index 376097f7b..1f56d6cf6 100644
--- a/numpy/core/tests/test_api.py
+++ b/numpy/core/tests/test_api.py
@@ -276,5 +276,13 @@ def test_contiguous_flags():
check_contig(a.ravel(), True, True)
check_contig(np.ones((1,3,1)).squeeze(), True, True)
+def test_broadcast_arrays():
+ # Test user defined dtypes
+ a = np.array([(1,2,3)], dtype='u4,u4,u4')
+ b = np.array([(1,2,3),(4,5,6),(7,8,9)], dtype='u4,u4,u4')
+ result = np.broadcast_arrays(a, b)
+ assert_equal(result[0], np.array([(1,2,3),(1,2,3),(1,2,3)], dtype='u4,u4,u4'))
+ assert_equal(result[1], np.array([(1,2,3),(4,5,6),(7,8,9)], dtype='u4,u4,u4'))
+
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index cb8415ee7..bb0bf029b 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -1898,6 +1898,11 @@ class TestRegression(TestCase):
order='F')
assert_array_equal(arr2, data_back)
+ def test_structured_count_nonzero(self):
+ arr = np.array([0, 1]).astype('i4, (2)i4')[:1]
+ count = np.count_nonzero(arr)
+ assert_equal(count, 0)
+
diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py
index 816b22052..3005da8da 100644
--- a/numpy/core/tests/test_ufunc.py
+++ b/numpy/core/tests/test_ufunc.py
@@ -5,6 +5,7 @@ import sys
import numpy as np
from numpy.testing import *
import numpy.core.umath_tests as umt
+import numpy.core.operand_flag_tests as opflag_tests
from numpy.compat import asbytes
from numpy.core.test_rational import *
@@ -799,6 +800,19 @@ class TestUfunc(TestCase):
# no output type should raise TypeError
assert_raises(TypeError, test_add, a, b)
+
+ def test_operand_flags(self):
+ a = np.arange(16, dtype='i8').reshape(4,4)
+ b = np.arange(9, dtype='i8').reshape(3,3)
+ opflag_tests.inplace_add(a[:-1,:-1], b)
+ assert_equal(a, np.array([[0,2,4,3],[7,9,11,7],
+ [14,16,18,11],[12,13,14,15]], dtype='i8'))
+
+ a = np.array(0)
+ opflag_tests.inplace_add(a, 3)
+ assert_equal(a, 3)
+ opflag_tests.inplace_add(a, [3, 4])
+ assert_equal(a, 10)
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/lib/arraypad.py b/numpy/lib/arraypad.py
index 112a8dae9..09ca99332 100644
--- a/numpy/lib/arraypad.py
+++ b/numpy/lib/arraypad.py
@@ -11,18 +11,18 @@ from numpy.compat import long
__all__ = ['pad']
-################################################################################
+###############################################################################
# Private utility functions.
def _create_vector(vector, pad_tuple, before_val, after_val):
- '''
+ """
Private function which creates the padded vector.
Parameters
----------
vector : ndarray of rank 1, length N + pad_tuple[0] + pad_tuple[1]
- Input vector including blank padded values. `N` is the lenth of the
+ Input vector including blank padded values. `N` is the lenth of the
original vector.
pad_tuple : tuple
This tuple represents the (before, after) width of the padding along
@@ -36,7 +36,8 @@ def _create_vector(vector, pad_tuple, before_val, after_val):
-------
_create_vector : ndarray
Vector with before_val and after_val replacing the blank pad values.
- '''
+
+ """
vector[:pad_tuple[0]] = before_val
if pad_tuple[1] > 0:
vector[-pad_tuple[1]:] = after_val
@@ -44,7 +45,7 @@ def _create_vector(vector, pad_tuple, before_val, after_val):
def _normalize_shape(narray, shape):
- '''
+ """
Private function which does some checks and normalizes the possibly
much simpler representations of 'pad_width', 'stat_length',
'constant_values', 'end_values'.
@@ -69,11 +70,12 @@ def _normalize_shape(narray, shape):
int => ((int, int), (int, int), ...)
[[int1, int2], [int3, int4], ...] => ((int1, int2), (int3, int4), ...)
((int1, int2), (int3, int4), ...) => no change
- [[int1, int2], ] => ((int1, int2), (int1, int2), ...]
+ [[int1, int2], ] => ((int1, int2), (int1, int2), ...)
((int1, int2), ) => ((int1, int2), (int1, int2), ...)
- [[int , ), ) => ((int, int), (int, int), ...)
+ [[int , ], ] => ((int, int), (int, int), ...)
((int , ), ) => ((int, int), (int, int), ...)
- '''
+
+ """
normshp = None
shapelen = len(np.shape(narray))
if (isinstance(shape, int)):
@@ -94,14 +96,14 @@ def _normalize_shape(narray, shape):
and isinstance(shape[0], (int, float, long))
and len(shape) == 2):
normshp = (shape, ) * shapelen
- if normshp == None:
+ if normshp is None:
fmt = "Unable to create correctly shaped tuple from %s"
raise ValueError(fmt % (shape,))
return normshp
def _validate_lengths(narray, number_elements):
- '''
+ """
Private function which does some checks and reformats pad_width and
stat_length using _normalize_shape.
@@ -125,22 +127,22 @@ def _validate_lengths(narray, number_elements):
int => ((int, int), (int, int), ...)
[[int1, int2], [int3, int4], ...] => ((int1, int2), (int3, int4), ...)
((int1, int2), (int3, int4), ...) => no change
- [[int1, int2], ] => ((int1, int2), (int1, int2), ...]
+ [[int1, int2], ] => ((int1, int2), (int1, int2), ...)
((int1, int2), ) => ((int1, int2), (int1, int2), ...)
- [[int , ), ) => ((int, int), (int, int), ...)
+ [[int , ], ] => ((int, int), (int, int), ...)
((int , ), ) => ((int, int), (int, int), ...)
- '''
- shapelen = len(np.shape(narray))
+
+ """
normshp = _normalize_shape(narray, number_elements)
for i in normshp:
if i[0] < 0 or i[1] < 0:
- fmt ="%s cannot contain negative values."
+ fmt = "%s cannot contain negative values."
raise ValueError(fmt % (number_elements,))
return normshp
def _create_stat_vectors(vector, pad_tuple, iaxis, kwargs):
- '''
+ """
Returns the portion of the vector required for any statistic.
Parameters
@@ -153,7 +155,7 @@ def _create_stat_vectors(vector, pad_tuple, iaxis, kwargs):
iaxis : int
The axis currently being looped across.
kwargs : keyword arguments
- Keyword arguments. Only 'stat_length' is used. 'stat_length'
+ Keyword arguments. Only 'stat_length' is used. 'stat_length'
defaults to the entire vector if not supplied.
Return
@@ -161,7 +163,8 @@ def _create_stat_vectors(vector, pad_tuple, iaxis, kwargs):
_create_stat_vectors : ndarray
The values from the original vector that will be used to calculate
the statistic.
- '''
+
+ """
# Can't have 0 represent the end if a slice... a[1:0] doesnt' work
pt1 = -pad_tuple[1]
@@ -186,7 +189,7 @@ def _create_stat_vectors(vector, pad_tuple, iaxis, kwargs):
def _maximum(vector, pad_tuple, iaxis, kwargs):
- '''
+ """
Private function to calculate the before/after vectors for pad_maximum.
Parameters
@@ -199,20 +202,21 @@ def _maximum(vector, pad_tuple, iaxis, kwargs):
iaxis : int
The axis currently being looped across.
kwargs : keyword arguments
- Keyword arguments. Only 'stat_length' is used. 'stat_length'
+ Keyword arguments. Only 'stat_length' is used. 'stat_length'
defaults to the entire vector if not supplied.
Return
------
_maximum : ndarray
Padded vector
- '''
+
+ """
sbvec, savec = _create_stat_vectors(vector, pad_tuple, iaxis, kwargs)
return _create_vector(vector, pad_tuple, max(sbvec), max(savec))
def _minimum(vector, pad_tuple, iaxis, kwargs):
- '''
+ """
Private function to calculate the before/after vectors for pad_minimum.
Parameters
@@ -225,20 +229,21 @@ def _minimum(vector, pad_tuple, iaxis, kwargs):
iaxis : int
The axis currently being looped across.
kwargs : keyword arguments
- Keyword arguments. Only 'stat_length' is used. 'stat_length'
+ Keyword arguments. Only 'stat_length' is used. 'stat_length'
defaults to the entire vector if not supplied.
Return
------
_minimum : ndarray
Padded vector
- '''
+
+ """
sbvec, savec = _create_stat_vectors(vector, pad_tuple, iaxis, kwargs)
return _create_vector(vector, pad_tuple, min(sbvec), min(savec))
def _median(vector, pad_tuple, iaxis, kwargs):
- '''
+ """
Private function to calculate the before/after vectors for pad_median.
Parameters
@@ -251,21 +256,22 @@ def _median(vector, pad_tuple, iaxis, kwargs):
iaxis : int
The axis currently being looped across.
kwargs : keyword arguments
- Keyword arguments. Only 'stat_length' is used. 'stat_length'
+ Keyword arguments. Only 'stat_length' is used. 'stat_length'
defaults to the entire vector if not supplied.
Return
------
_median : ndarray
Padded vector
- '''
+
+ """
sbvec, savec = _create_stat_vectors(vector, pad_tuple, iaxis, kwargs)
return _create_vector(vector, pad_tuple, np.median(sbvec),
np.median(savec))
def _mean(vector, pad_tuple, iaxis, kwargs):
- '''
+ """
Private function to calculate the before/after vectors for pad_mean.
Parameters
@@ -278,21 +284,22 @@ def _mean(vector, pad_tuple, iaxis, kwargs):
iaxis : int
The axis currently being looped across.
kwargs : keyword arguments
- Keyword arguments. Only 'stat_length' is used. 'stat_length'
+ Keyword arguments. Only 'stat_length' is used. 'stat_length'
defaults to the entire vector if not supplied.
Return
------
_mean : ndarray
Padded vector
- '''
+
+ """
sbvec, savec = _create_stat_vectors(vector, pad_tuple, iaxis, kwargs)
return _create_vector(vector, pad_tuple, np.average(sbvec),
np.average(savec))
def _constant(vector, pad_tuple, iaxis, kwargs):
- '''
+ """
Private function to calculate the before/after vectors for
pad_constant.
@@ -306,19 +313,20 @@ def _constant(vector, pad_tuple, iaxis, kwargs):
iaxis : int
The axis currently being looped across.
kwargs : keyword arguments
- Keyword arguments. Need 'constant_values' keyword argument.
+ Keyword arguments. Need 'constant_values' keyword argument.
Return
------
_constant : ndarray
Padded vector
- '''
+
+ """
nconstant = kwargs['constant_values'][iaxis]
return _create_vector(vector, pad_tuple, nconstant[0], nconstant[1])
def _linear_ramp(vector, pad_tuple, iaxis, kwargs):
- '''
+ """
Private function to calculate the before/after vectors for
pad_linear_ramp.
@@ -330,7 +338,7 @@ def _linear_ramp(vector, pad_tuple, iaxis, kwargs):
This tuple represents the (before, after) width of the padding
along this particular iaxis.
iaxis : int
- The axis currently being looped across. Not used in _linear_ramp.
+ The axis currently being looped across. Not used in _linear_ramp.
kwargs : keyword arguments
Keyword arguments. Not used in _linear_ramp.
@@ -338,7 +346,8 @@ def _linear_ramp(vector, pad_tuple, iaxis, kwargs):
------
_linear_ramp : ndarray
Padded vector
- '''
+
+ """
end_values = kwargs['end_values'][iaxis]
before_delta = ((vector[pad_tuple[0]] - end_values[0])
/ float(pad_tuple[0]))
@@ -360,7 +369,7 @@ def _linear_ramp(vector, pad_tuple, iaxis, kwargs):
def _reflect(vector, pad_tuple, iaxis, kwargs):
- '''
+ """
Private function to calculate the before/after vectors for pad_reflect.
Parameters
@@ -371,7 +380,7 @@ def _reflect(vector, pad_tuple, iaxis, kwargs):
This tuple represents the (before, after) width of the padding
along this particular iaxis.
iaxis : int
- The axis currently being looped across. Not used in _reflect.
+ The axis currently being looped across. Not used in _reflect.
kwargs : keyword arguments
Keyword arguments. Not used in _reflect.
@@ -379,7 +388,8 @@ def _reflect(vector, pad_tuple, iaxis, kwargs):
------
_reflect : ndarray
Padded vector
- '''
+
+ """
# Can't have pad_tuple[1] be used in the slice if == to 0.
if pad_tuple[1] == 0:
after_vector = vector[pad_tuple[0]:None]
@@ -389,11 +399,9 @@ def _reflect(vector, pad_tuple, iaxis, kwargs):
reverse = after_vector[::-1]
before_vector = np.resize(
- np.concatenate(
- (after_vector[1:-1], reverse)), pad_tuple[0])[::-1]
+ np.concatenate((after_vector[1:-1], reverse)), pad_tuple[0])[::-1]
after_vector = np.resize(
- np.concatenate(
- (reverse[1:-1], after_vector)), pad_tuple[1])
+ np.concatenate((reverse[1:-1], after_vector)), pad_tuple[1])
if kwargs['reflect_type'] == 'even':
pass
@@ -402,12 +410,12 @@ def _reflect(vector, pad_tuple, iaxis, kwargs):
after_vector = 2 * vector[-pad_tuple[-1] - 1] - after_vector
else:
raise ValueError("The keyword '%s' cannot have the value '%s'."
- % ('reflect_type', kwargs['reflect_type']))
+ % ('reflect_type', kwargs['reflect_type']))
return _create_vector(vector, pad_tuple, before_vector, after_vector)
def _symmetric(vector, pad_tuple, iaxis, kwargs):
- '''
+ """
Private function to calculate the before/after vectors for
pad_symmetric.
@@ -419,7 +427,7 @@ def _symmetric(vector, pad_tuple, iaxis, kwargs):
This tuple represents the (before, after) width of the padding
along this particular iaxis.
iaxis : int
- The axis currently being looped across. Not used in _symmetric.
+ The axis currently being looped across. Not used in _symmetric.
kwargs : keyword arguments
Keyword arguments. Not used in _symmetric.
@@ -427,16 +435,19 @@ def _symmetric(vector, pad_tuple, iaxis, kwargs):
------
_symmetric : ndarray
Padded vector
- '''
+
+ """
if pad_tuple[1] == 0:
after_vector = vector[pad_tuple[0]:None]
else:
after_vector = vector[pad_tuple[0]:-pad_tuple[1]]
- before_vector = np.resize( np.concatenate( (after_vector,
- after_vector[::-1])), pad_tuple[0])[::-1]
- after_vector = np.resize( np.concatenate( (after_vector[::-1],
- after_vector)), pad_tuple[1])
+ before_vector = np.resize(
+ np.concatenate((after_vector, after_vector[::-1])),
+ pad_tuple[0])[::-1]
+ after_vector = np.resize(
+ np.concatenate((after_vector[::-1], after_vector)),
+ pad_tuple[1])
if kwargs['reflect_type'] == 'even':
pass
@@ -445,12 +456,12 @@ def _symmetric(vector, pad_tuple, iaxis, kwargs):
after_vector = 2 * vector[-pad_tuple[1] - 1] - after_vector
else:
raise ValueError("The keyword '%s' cannot have the value '%s'."
- % ('reflect_type', kwargs['reflect_type']))
+ % ('reflect_type', kwargs['reflect_type']))
return _create_vector(vector, pad_tuple, before_vector, after_vector)
def _wrap(vector, pad_tuple, iaxis, kwargs):
- '''
+ """
Private function to calculate the before/after vectors for pad_wrap.
Parameters
@@ -469,7 +480,8 @@ def _wrap(vector, pad_tuple, iaxis, kwargs):
------
_wrap : ndarray
Padded vector
- '''
+
+ """
if pad_tuple[1] == 0:
after_vector = vector[pad_tuple[0]:None]
else:
@@ -482,7 +494,7 @@ def _wrap(vector, pad_tuple, iaxis, kwargs):
def _edge(vector, pad_tuple, iaxis, kwargs):
- '''
+ """
Private function to calculate the before/after vectors for pad_edge.
Parameters
@@ -501,12 +513,13 @@ def _edge(vector, pad_tuple, iaxis, kwargs):
------
_edge : ndarray
Padded vector
- '''
+
+ """
return _create_vector(vector, pad_tuple, vector[pad_tuple[0]],
vector[-pad_tuple[1] - 1])
-################################################################################
+###############################################################################
# Public functions
@@ -695,44 +708,44 @@ def pad(array, pad_width, mode=None, **kwargs):
[10, 10, 3, 4, 5, 10, 10],
[10, 10, 10, 10, 10, 10, 10],
[10, 10, 10, 10, 10, 10, 10]])
- """
+ """
narray = np.array(array)
pad_width = _validate_lengths(narray, pad_width)
modefunc = {
- 'constant': _constant,
- 'edge': _edge,
- 'linear_ramp': _linear_ramp,
- 'maximum': _maximum,
- 'mean': _mean,
- 'median': _median,
- 'minimum': _minimum,
- 'reflect': _reflect,
- 'symmetric': _symmetric,
- 'wrap': _wrap,
- }
+ 'constant': _constant,
+ 'edge': _edge,
+ 'linear_ramp': _linear_ramp,
+ 'maximum': _maximum,
+ 'mean': _mean,
+ 'median': _median,
+ 'minimum': _minimum,
+ 'reflect': _reflect,
+ 'symmetric': _symmetric,
+ 'wrap': _wrap,
+ }
allowedkwargs = {
- 'constant': ['constant_values'],
- 'edge': [],
- 'linear_ramp': ['end_values'],
- 'maximum': ['stat_length'],
- 'mean': ['stat_length'],
- 'median': ['stat_length'],
- 'minimum': ['stat_length'],
- 'reflect': ['reflect_type'],
- 'symmetric': ['reflect_type'],
- 'wrap': [],
- }
+ 'constant': ['constant_values'],
+ 'edge': [],
+ 'linear_ramp': ['end_values'],
+ 'maximum': ['stat_length'],
+ 'mean': ['stat_length'],
+ 'median': ['stat_length'],
+ 'minimum': ['stat_length'],
+ 'reflect': ['reflect_type'],
+ 'symmetric': ['reflect_type'],
+ 'wrap': [],
+ }
kwdefaults = {
- 'stat_length': None,
- 'constant_values': 0,
- 'end_values': 0,
- 'reflect_type': 'even',
- }
+ 'stat_length': None,
+ 'constant_values': 0,
+ 'end_values': 0,
+ 'reflect_type': 'even',
+ }
if isinstance(mode, str):
function = modefunc[mode]
@@ -741,7 +754,7 @@ def pad(array, pad_width, mode=None, **kwargs):
for key in kwargs:
if key not in allowedkwargs[mode]:
raise ValueError('%s keyword not in allowed keywords %s' %
- (key, allowedkwargs[mode]))
+ (key, allowedkwargs[mode]))
# Set kwarg defaults
for kw in allowedkwargs[mode]:
@@ -753,9 +766,9 @@ def pad(array, pad_width, mode=None, **kwargs):
kwargs[i] = _validate_lengths(narray, kwargs[i])
if i in ['end_values', 'constant_values']:
kwargs[i] = _normalize_shape(narray, kwargs[i])
- elif mode == None:
+ elif mode is None:
raise ValueError('Keyword "mode" must be a function or one of %s.' %
- (list(modefunc.keys()),))
+ (list(modefunc.keys()),))
else:
# User supplied function, I hope
function = mode
@@ -781,4 +794,3 @@ def pad(array, pad_width, mode=None, **kwargs):
iaxis,
kwargs)
return newmat
-
diff --git a/numpy/lib/stride_tricks.py b/numpy/lib/stride_tricks.py
index 1f08131ec..7b6b06fdc 100644
--- a/numpy/lib/stride_tricks.py
+++ b/numpy/lib/stride_tricks.py
@@ -27,7 +27,10 @@ def as_strided(x, shape=None, strides=None):
interface['shape'] = tuple(shape)
if strides is not None:
interface['strides'] = tuple(strides)
- return np.asarray(DummyArray(interface, base=x))
+ array = np.asarray(DummyArray(interface, base=x))
+ # Make sure dtype is correct in case of custom dtype
+ array.dtype = x.dtype
+ return array
def broadcast_arrays(*args):
"""
diff --git a/numpy/testing/nosetester.py b/numpy/testing/nosetester.py
index d07a5ad0b..e3f96b9a9 100644
--- a/numpy/testing/nosetester.py
+++ b/numpy/testing/nosetester.py
@@ -188,6 +188,14 @@ class NoseTester(object):
label = 'not slow'
argv += ['-A', label]
argv += ['--verbosity', str(verbose)]
+
+ # When installing with setuptools, and also in some other cases, the
+ # test_*.py files end up marked +x executable. Nose, by default, does
+ # not run files marked with +x as they might be scripts. However, in
+ # our case nose only looks for test_*.py files under the package
+ # directory, which should be safe.
+ argv += ['--exe']
+
if extra_argv:
argv += extra_argv
return argv