diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2014-07-27 18:14:57 -0500 |
---|---|---|
committer | Charles Harris <charlesr.harris@gmail.com> | 2014-07-27 18:14:57 -0500 |
commit | bc4a583d19fc694659d33c59e16b4cedd6307432 (patch) | |
tree | fe6f2c1b4f002a9e5447780fb37bd8b54dd37cb7 | |
parent | 656cf247e531c1ebfb69e864e00620b10082b120 (diff) | |
parent | 91369d30a13dcc6484f27195d73e6ea9ba2edd2d (diff) | |
download | numpy-bc4a583d19fc694659d33c59e16b4cedd6307432.tar.gz |
Merge pull request #4902 from juliantaylor/asarray-improve
ENH: add a ndarray super-fast path to _array_from_object
-rw-r--r-- | numpy/core/src/multiarray/ctors.c | 5 | ||||
-rw-r--r-- | numpy/core/src/multiarray/multiarraymodule.c | 103 | ||||
-rw-r--r-- | numpy/core/src/multiarray/multiarraymodule.h | 11 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 27 |
4 files changed, 144 insertions, 2 deletions
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index 3da2dfae7..c57df147a 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -12,6 +12,7 @@ #include "npy_config.h" #include "npy_pycompat.h" +#include "multiarraymodule.h" #include "common.h" #include "ctors.h" @@ -1069,7 +1070,7 @@ PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd, if ((subtype != &PyArray_Type)) { PyObject *res, *func, *args; - func = PyObject_GetAttrString((PyObject *)fa, "__array_finalize__"); + func = PyObject_GetAttr((PyObject *)fa, npy_ma_str_array_finalize); if (func && func != Py_None) { if (NpyCapsule_Check(func)) { /* A C-function is stored here */ @@ -3368,7 +3369,7 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type, #endif ) { PyObject *newbuf; - newbuf = PyObject_GetAttrString(buf, "__buffer__"); + newbuf = PyObject_GetAttr(buf, npy_ma_str_buffer); if (newbuf == NULL) { Py_DECREF(type); return NULL; diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index 7fade0832..a31751ec6 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -56,6 +56,7 @@ NPY_NO_EXPORT int NPY_NUMUSERTYPES = 0; #include "common.h" #include "ufunc_override.h" #include "scalarmathmodule.h" /* for npy_mul_with_overflow_intp */ +#include "multiarraymodule.h" /* Only here for API compatibility */ NPY_NO_EXPORT PyTypeObject PyBigArray_Type; @@ -1615,6 +1616,72 @@ _array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws) "only 2 non-keyword arguments accepted"); return NULL; } + + /* super-fast path for ndarray argument calls */ + if (PyTuple_GET_SIZE(args) == 0) { + goto full_path; + } + op = PyTuple_GET_ITEM(args, 0); + if (PyArray_CheckExact(op)) { + PyObject * dtype_obj = Py_None; + oparr = (PyArrayObject *)op; + /* get dtype which can be positional */ + if (PyTuple_GET_SIZE(args) == 2) { + dtype_obj = PyTuple_GET_ITEM(args, 1); + } + else if (kws) { + dtype_obj = PyDict_GetItem(kws, npy_ma_str_dtype); + if (dtype_obj == NULL) { + dtype_obj = Py_None; + } + } + if (dtype_obj != Py_None) { + goto full_path; + } + + /* array(ndarray) */ + if (kws == NULL) { + ret = (PyArrayObject *)PyArray_NewCopy(oparr, order); + goto finish; + } + else { + /* fast path for copy=False rest default (np.asarray) */ + PyObject * copy_obj, * order_obj, *ndmin_obj; + copy_obj = PyDict_GetItem(kws, npy_ma_str_copy); + if (copy_obj != Py_False) { + goto full_path; + } + copy = NPY_FALSE; + + /* order does not matter for 1d arrays */ + if (PyArray_NDIM(op) > 1) { + order_obj = PyDict_GetItem(kws, npy_ma_str_order); + if (order_obj != Py_None && order_obj != NULL) { + goto full_path; + } + } + + ndmin_obj = PyDict_GetItem(kws, npy_ma_str_ndmin); + if (ndmin_obj) { + ndmin = PyLong_AsLong(ndmin_obj); + if (ndmin == -1 && PyErr_Occurred()) { + goto clean_type; + } + else if (ndmin > NPY_MAXDIMS) { + goto full_path; + } + } + + /* copy=False with default dtype, order and ndim */ + if (STRIDING_OK(oparr, order)) { + ret = oparr; + Py_INCREF(ret); + goto finish; + } + } + } + +full_path: if(!PyArg_ParseTupleAndKeywords(args, kws, "O|O&O&O&O&i", kwd, &op, PyArray_DescrConverter2, &type, @@ -4022,6 +4089,38 @@ set_flaginfo(PyObject *d) return; } +NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array = NULL; +NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array_prepare = NULL; +NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array_wrap = NULL; +NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array_finalize = NULL; +NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_buffer = NULL; +NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_ufunc = NULL; +NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_order = NULL; +NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_copy = NULL; +NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_dtype = NULL; +NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_ndmin = NULL; + +static int +intern_strings(void) +{ + npy_ma_str_array = PyUString_InternFromString("__array__"); + npy_ma_str_array_prepare = PyUString_InternFromString("__array_prepare__"); + npy_ma_str_array_wrap = PyUString_InternFromString("__array_wrap__"); + npy_ma_str_array_finalize = PyUString_InternFromString("__array_finalize__"); + npy_ma_str_buffer = PyUString_InternFromString("__buffer__"); + npy_ma_str_ufunc = PyUString_InternFromString("__numpy_ufunc__"); + npy_ma_str_order = PyUString_InternFromString("order"); + npy_ma_str_copy = PyUString_InternFromString("copy"); + npy_ma_str_dtype = PyUString_InternFromString("dtype"); + npy_ma_str_ndmin = PyUString_InternFromString("ndmin"); + + return npy_ma_str_array && npy_ma_str_array_prepare && + npy_ma_str_array_wrap && npy_ma_str_array_finalize && + npy_ma_str_array_finalize && npy_ma_str_ufunc && + npy_ma_str_order && npy_ma_str_copy && npy_ma_str_dtype && + npy_ma_str_ndmin; +} + #if defined(NPY_PY3K) static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, @@ -4194,6 +4293,10 @@ PyMODINIT_FUNC initmultiarray(void) { set_flaginfo(d); + if (!intern_strings()) { + goto err; + } + if (set_typeinfo(d) != 0) { goto err; } diff --git a/numpy/core/src/multiarray/multiarraymodule.h b/numpy/core/src/multiarray/multiarraymodule.h index 5a3b14b0b..82ae24845 100644 --- a/numpy/core/src/multiarray/multiarraymodule.h +++ b/numpy/core/src/multiarray/multiarraymodule.h @@ -1,4 +1,15 @@ #ifndef _NPY_MULTIARRAY_H_ #define _NPY_MULTIARRAY_H_ +NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array; +NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array_prepare; +NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array_wrap; +NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array_finalize; +NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_buffer; +NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_ufunc; +NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_order; +NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_copy; +NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_dtype; +NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_ndmin; + #endif diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 4c0bc428a..221a930c2 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -246,6 +246,33 @@ class TestArrayConstruction(TestCase): r = np.array([[True, False], [True, False], [False, True]]) assert_equal(r, tgt.T) + def test_array_empty(self): + assert_raises(TypeError, np.array) + + def test_array_copy_false(self): + d = np.array([1, 2, 3]) + e = np.array(d, copy=False) + d[1] = 3 + assert_array_equal(e, [1, 3, 3]) + e = np.array(d, copy=False, order='F') + d[1] = 4 + assert_array_equal(e, [1, 4, 3]) + e[2] = 7 + assert_array_equal(d, [1, 4, 7]) + + def test_array_copy_true(self): + d = np.array([[1,2,3], [1, 2, 3]]) + e = np.array(d, copy=True) + d[0, 1] = 3 + e[0, 2] = -7 + assert_array_equal(e, [[1, 2, -7], [1, 2, 3]]) + assert_array_equal(d, [[1, 3, 3], [1, 2, 3]]) + e = np.array(d, copy=True, order='F') + d[0, 1] = 5 + e[0, 2] = 7 + assert_array_equal(e, [[1, 3, 7], [1, 2, 3]]) + assert_array_equal(d, [[1, 5, 3], [1,2,3]]) + class TestAssignment(TestCase): def test_assignment_broadcasting(self): |