summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorm-d-w <mw9050@gmail.com>2013-06-06 14:57:16 -0400
committerm-d-w <mw9050@gmail.com>2013-06-10 18:17:52 -0400
commit3abe4fd00ab1eead3a5a35163821a3edac504a36 (patch)
tree465e82b24cd16455cc41ef7e346e2db4eb255390
parent16c55bad4aa4c49116d963eee85550258c83b934 (diff)
downloadnumpy-3abe4fd00ab1eead3a5a35163821a3edac504a36.tar.gz
ENH: Optimize array creation by avoiding errors
-rw-r--r--numpy/core/src/multiarray/common.c122
-rw-r--r--numpy/core/src/multiarray/common.h3
-rw-r--r--numpy/core/src/multiarray/ctors.c62
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c3
4 files changed, 126 insertions, 64 deletions
diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c
index 01bf9cd74..4787c6482 100644
--- a/numpy/core/src/multiarray/common.c
+++ b/numpy/core/src/multiarray/common.c
@@ -27,6 +27,60 @@
* be allowed under the NPY_SAME_KIND_CASTING rules, and if not we issue a
* warning (that people's code will be broken in a future release.)
*/
+
+/*
+ * PyArray_GetAttrString_SuppressException:
+ *
+ * Stripped down version of PyObject_GetAttrString,
+ * avoids lookups for None, tuple, and List objects,
+ * and doesn't create a PyErr since this code ignores it.
+ *
+ * This can be much faster then PyObject_GetAttrString where
+ * exceptions are not used by caller.
+ *
+ * 'obj' is the object to search for attribute.
+ *
+ * 'name' is the attribute to search for.
+ *
+ * Returns attribute value on success, 0 on failure.
+ */
+PyObject *
+PyArray_GetAttrString_SuppressException(PyObject *obj, char *name)
+{
+ PyTypeObject *tp = Py_TYPE(obj);
+ PyObject *res = (PyObject *)NULL;
+ if (/* Is not trivial type */
+ obj != Py_None &&
+ !PyList_CheckExact(obj) &&
+ !PyTuple_CheckExact(obj)) {
+ /* Attribute referenced by (char *)name */
+ if (tp->tp_getattr != NULL) {
+ res = (*tp->tp_getattr)(obj, name);
+ if (res == NULL) {
+ PyErr_Clear();
+ }
+ }
+ /* Attribute referenced by (PyObject *)name */
+ else if (tp->tp_getattro != NULL) {
+#if defined(NPY_PY3K)
+ PyObject *w = PyUnicode_InternFromString(name);
+#else
+ PyObject *w = PyString_InternFromString(name);
+#endif
+ if (w == NULL)
+ return (PyObject *)NULL;
+ Py_DECREF(w);
+ res = (*tp->tp_getattro)(obj, w);
+ if (res == NULL) {
+ PyErr_Clear();
+ }
+ }
+ }
+ return res;
+}
+
+
+
NPY_NO_EXPORT NPY_CASTING NPY_DEFAULT_ASSIGN_CASTING = NPY_INTERNAL_UNSAFE_CASTING_BUT_WARN_UNLESS_SAME_KIND;
@@ -156,8 +210,17 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
goto promote_types;
}
+ /* See if it's a python None */
+ if (obj == Py_None) {
+ dtype = PyArray_DescrFromType(NPY_OBJECT);
+ if (dtype == NULL) {
+ goto fail;
+ }
+ Py_INCREF(dtype);
+ goto promote_types;
+ }
/* Check if it's a NumPy scalar */
- if (PyArray_IsScalar(obj, Generic)) {
+ else if (PyArray_IsScalar(obj, Generic)) {
if (!string_type) {
dtype = PyArray_DescrFromScalar(obj);
if (dtype == NULL) {
@@ -308,32 +371,35 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
}
/* PEP 3118 buffer interface */
- memset(&buffer_view, 0, sizeof(Py_buffer));
- if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT|PyBUF_STRIDES) == 0 ||
- PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT) == 0) {
-
- PyErr_Clear();
- dtype = _descriptor_from_pep3118_format(buffer_view.format);
- PyBuffer_Release(&buffer_view);
- if (dtype) {
+ if (PyObject_CheckBuffer(obj) == 1) {
+ memset(&buffer_view, 0, sizeof(Py_buffer));
+ if (PyObject_GetBuffer(obj, &buffer_view,
+ PyBUF_FORMAT|PyBUF_STRIDES) == 0 ||
+ PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT) == 0) {
+
+ PyErr_Clear();
+ dtype = _descriptor_from_pep3118_format(buffer_view.format);
+ PyBuffer_Release(&buffer_view);
+ if (dtype) {
+ goto promote_types;
+ }
+ }
+ else if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 ||
+ PyObject_GetBuffer(obj, &buffer_view, PyBUF_SIMPLE) == 0) {
+
+ PyErr_Clear();
+ dtype = PyArray_DescrNewFromType(NPY_VOID);
+ dtype->elsize = buffer_view.itemsize;
+ PyBuffer_Release(&buffer_view);
goto promote_types;
}
- }
- else if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 ||
- PyObject_GetBuffer(obj, &buffer_view, PyBUF_SIMPLE) == 0) {
-
- PyErr_Clear();
- dtype = PyArray_DescrNewFromType(NPY_VOID);
- dtype->elsize = buffer_view.itemsize;
- PyBuffer_Release(&buffer_view);
- goto promote_types;
- }
- else {
- PyErr_Clear();
+ else {
+ PyErr_Clear();
+ }
}
/* The array interface */
- ip = PyObject_GetAttrString(obj, "__array_interface__");
+ ip = PyArray_GetAttrString_SuppressException(obj, "__array_interface__");
if (ip != NULL) {
if (PyDict_Check(ip)) {
PyObject *typestr;
@@ -364,12 +430,9 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
}
Py_DECREF(ip);
}
- else {
- PyErr_Clear();
- }
/* The array struct interface */
- ip = PyObject_GetAttrString(obj, "__array_struct__");
+ ip = PyArray_GetAttrString_SuppressException(obj, "__array_struct__");
if (ip != NULL) {
PyArrayInterface *inter;
char buf[40];
@@ -389,9 +452,6 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
}
Py_DECREF(ip);
}
- else {
- PyErr_Clear();
- }
/* The old buffer interface */
#if !defined(NPY_PY3K)
@@ -407,7 +467,9 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
#endif
/* The __array__ attribute */
- if (PyObject_HasAttrString(obj, "__array__")) {
+ ip = PyArray_GetAttrString_SuppressException(obj, "__array__");
+ if (ip != NULL) {
+ Py_DECREF(ip);
ip = PyObject_CallMethod(obj, "__array__", NULL);
if(ip && PyArray_Check(ip)) {
dtype = PyArray_DESCR((PyArrayObject *)ip);
diff --git a/numpy/core/src/multiarray/common.h b/numpy/core/src/multiarray/common.h
index a474cf820..68f8d246d 100644
--- a/numpy/core/src/multiarray/common.h
+++ b/numpy/core/src/multiarray/common.h
@@ -25,6 +25,9 @@ NPY_NO_EXPORT int
PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
PyArray_Descr **out_dtype, int string_status);
+NPY_NO_EXPORT PyObject *
+PyArray_GetAttrString_SuppressException(PyObject *v, char *name);
+
/*
* Returns NULL without setting an exception if no scalar is matched, a
* new dtype reference otherwise.
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c
index 5c692bd02..c96258417 100644
--- a/numpy/core/src/multiarray/ctors.c
+++ b/numpy/core/src/multiarray/ctors.c
@@ -646,32 +646,35 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
/* obj is a PEP 3118 buffer */
#if PY_VERSION_HEX >= 0x02060000
/* PEP 3118 buffer interface */
- memset(&buffer_view, 0, sizeof(Py_buffer));
- if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 ||
- PyObject_GetBuffer(obj, &buffer_view, PyBUF_ND) == 0) {
- int nd = buffer_view.ndim;
- if (nd < *maxndim) {
- *maxndim = nd;
+ if (PyObject_CheckBuffer(obj) == 1) {
+ memset(&buffer_view, 0, sizeof(Py_buffer));
+ if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 ||
+ PyObject_GetBuffer(obj, &buffer_view, PyBUF_ND) == 0) {
+ int nd = buffer_view.ndim;
+ if (nd < *maxndim) {
+ *maxndim = nd;
+ }
+ for (i=0; i<*maxndim; i++) {
+ d[i] = buffer_view.shape[i];
+ }
+ PyBuffer_Release(&buffer_view);
+ return 0;
}
- for (i=0; i<*maxndim; i++) {
- d[i] = buffer_view.shape[i];
+ else if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_SIMPLE) == 0) {
+ d[0] = buffer_view.len;
+ *maxndim = 1;
+ PyBuffer_Release(&buffer_view);
+ return 0;
+ }
+ else {
+ PyErr_Clear();
}
- PyBuffer_Release(&buffer_view);
- return 0;
- }
- else if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_SIMPLE) == 0) {
- d[0] = buffer_view.len;
- *maxndim = 1;
- PyBuffer_Release(&buffer_view);
- return 0;
- }
- else {
- PyErr_Clear();
}
#endif
/* obj has the __array_struct__ interface */
- if ((e = PyObject_GetAttrString(obj, "__array_struct__")) != NULL) {
+ e = PyArray_GetAttrString_SuppressException(obj, "__array_struct__");
+ if (e != NULL) {
int nd = -1;
if (NpyCapsule_Check(e)) {
PyArrayInterface *inter;
@@ -693,12 +696,10 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
return 0;
}
}
- else {
- PyErr_Clear();
- }
/* obj has the __array_interface__ interface */
- if ((e = PyObject_GetAttrString(obj, "__array_interface__")) != NULL) {
+ e = PyArray_GetAttrString_SuppressException(obj, "__array_interface__");
+ if (e != NULL) {
int nd = -1;
if (PyDict_Check(e)) {
PyObject *new;
@@ -728,9 +729,6 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
return 0;
}
}
- else {
- PyErr_Clear();
- }
n = PySequence_Size(obj);
@@ -1934,9 +1932,8 @@ PyArray_FromStructInterface(PyObject *input)
PyArrayObject *ret;
char endian = NPY_NATBYTE;
- attr = PyObject_GetAttrString(input, "__array_struct__");
+ attr = PyArray_GetAttrString_SuppressException(input, "__array_struct__");
if (attr == NULL) {
- PyErr_Clear();
return Py_NotImplemented;
}
if (!NpyCapsule_Check(attr)) {
@@ -2009,9 +2006,9 @@ PyArray_FromInterface(PyObject *origin)
/* Get the memory from __array_data__ and __array_offset__ */
/* Get the strides */
- iface = PyObject_GetAttrString(origin, "__array_interface__");
+ iface = PyArray_GetAttrString_SuppressException(origin,
+ "__array_interface__");
if (iface == NULL) {
- PyErr_Clear();
return Py_NotImplemented;
}
if (!PyDict_Check(iface)) {
@@ -2226,9 +2223,8 @@ PyArray_FromArrayAttr(PyObject *op, PyArray_Descr *typecode, PyObject *context)
PyObject *new;
PyObject *array_meth;
- array_meth = PyObject_GetAttrString(op, "__array__");
+ array_meth = PyArray_GetAttrString_SuppressException(op, "__array__");
if (array_meth == NULL) {
- PyErr_Clear();
return Py_NotImplemented;
}
if (context == NULL) {
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index 7332a26d0..426ab695c 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -52,6 +52,7 @@ NPY_NO_EXPORT int NPY_NUMUSERTYPES = 0;
#include "shape.h"
#include "ctors.h"
#include "array_assign.h"
+#include "common.h"
/* Only here for API compatibility */
NPY_NO_EXPORT PyTypeObject PyBigArray_Type;
@@ -68,7 +69,7 @@ PyArray_GetPriority(PyObject *obj, double default_)
if (PyArray_CheckExact(obj))
return priority;
- ret = PyObject_GetAttrString(obj, "__array_priority__");
+ ret = PyArray_GetAttrString_SuppressException(obj, "__array_priority__");
if (ret != NULL) {
priority = PyFloat_AsDouble(ret);
}