summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2014-07-27 18:14:57 -0500
committerCharles Harris <charlesr.harris@gmail.com>2014-07-27 18:14:57 -0500
commitbc4a583d19fc694659d33c59e16b4cedd6307432 (patch)
treefe6f2c1b4f002a9e5447780fb37bd8b54dd37cb7
parent656cf247e531c1ebfb69e864e00620b10082b120 (diff)
parent91369d30a13dcc6484f27195d73e6ea9ba2edd2d (diff)
downloadnumpy-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.c5
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c103
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.h11
-rw-r--r--numpy/core/tests/test_multiarray.py27
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):