summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/src/multiarray/conversion_utils.c318
1 files changed, 133 insertions, 185 deletions
diff --git a/numpy/core/src/multiarray/conversion_utils.c b/numpy/core/src/multiarray/conversion_utils.c
index 27d435881..71690c20b 100644
--- a/numpy/core/src/multiarray/conversion_utils.c
+++ b/numpy/core/src/multiarray/conversion_utils.c
@@ -84,7 +84,7 @@ PyArray_OutputConverter(PyObject *object, PyArrayObject **address)
NPY_NO_EXPORT int
PyArray_IntpConverter(PyObject *obj, PyArray_Dims *seq)
{
- int len;
+ Py_ssize_t len;
int nd;
seq->ptr = NULL;
@@ -94,14 +94,15 @@ PyArray_IntpConverter(PyObject *obj, PyArray_Dims *seq)
}
len = PySequence_Size(obj);
if (len == -1) {
- /* Check to see if it is a number */
+ /* Check to see if it is an integer number */
if (PyNumber_Check(obj)) {
+ /* DEPRECATED: replace PyNumber_Check with PyIndex_Check */
len = 1;
}
}
if (len < 0) {
PyErr_SetString(PyExc_TypeError,
- "expected sequence object with len >= 0");
+ "expected sequence object with len >= 0 or a single integer");
return NPY_FAIL;
}
if (len > NPY_MAXDIMS) {
@@ -117,7 +118,7 @@ PyArray_IntpConverter(PyObject *obj, PyArray_Dims *seq)
}
}
seq->len = len;
- nd = PyArray_IntpFromSequence(obj, (npy_intp *)seq->ptr, len);
+ nd = PyArray_IntpFromSequence(obj, (npy_intp *)seq->ptr, (int) len);
if (nd == -1 || nd != len) {
PyDimMem_FREE(seq->ptr);
seq->ptr = NULL;
@@ -187,7 +188,7 @@ PyArray_AxisConverter(PyObject *obj, int *axis)
*axis = NPY_MAXDIMS;
}
else {
- *axis = (int) PyInt_AsLong(obj);
+ *axis = (int) PyArray_PyIntAsInt(obj);
if (PyErr_Occurred()) {
return NPY_FAIL;
}
@@ -223,9 +224,9 @@ PyArray_ConvertMultiAxis(PyObject *axis_in, int ndim, npy_bool *out_axis_flags)
}
for (i = 0; i < naxes; ++i) {
PyObject *tmp = PyTuple_GET_ITEM(axis_in, i);
- long axis = PyInt_AsLong(tmp);
- long axis_orig = axis;
- if (axis == -1 && PyErr_Occurred()) {
+ int axis = PyArray_PyIntAsInt(tmp);
+ int axis_orig = axis;
+ if (error_converting(axis)) {
return NPY_FAIL;
}
if (axis < 0) {
@@ -233,7 +234,7 @@ PyArray_ConvertMultiAxis(PyObject *axis_in, int ndim, npy_bool *out_axis_flags)
}
if (axis < 0 || axis >= ndim) {
PyErr_Format(PyExc_ValueError,
- "'axis' entry %ld is out of bounds [-%d, %d)",
+ "'axis' entry %d is out of bounds [-%d, %d)",
axis_orig, ndim, ndim);
return NPY_FAIL;
}
@@ -249,14 +250,14 @@ PyArray_ConvertMultiAxis(PyObject *axis_in, int ndim, npy_bool *out_axis_flags)
}
/* Try to interpret axis as an integer */
else {
- long axis, axis_orig;
+ int axis, axis_orig;
memset(out_axis_flags, 0, ndim);
- axis = PyInt_AsLong(axis_in);
+ axis = PyArray_PyIntAsInt(axis_in);
axis_orig = axis;
- /* TODO: PyNumber_Index would be good to use here */
- if (axis == -1 && PyErr_Occurred()) {
+
+ if (error_converting(axis)) {
return NPY_FAIL;
}
if (axis < 0) {
@@ -272,7 +273,7 @@ PyArray_ConvertMultiAxis(PyObject *axis_in, int ndim, npy_bool *out_axis_flags)
if (axis < 0 || axis >= ndim) {
PyErr_Format(PyExc_ValueError,
- "'axis' entry %ld is out of bounds [-%d, %d)",
+ "'axis' entry %d is out of bounds [-%d, %d)",
axis_orig, ndim, ndim);
return NPY_FAIL;
}
@@ -529,8 +530,8 @@ PyArray_ClipmodeConverter(PyObject *object, NPY_CLIPMODE *val)
return ret;
}
else {
- int number = PyInt_AsLong(object);
- if (number == -1 && PyErr_Occurred()) {
+ int number = PyArray_PyIntAsInt(object);
+ if (error_converting(number)) {
goto fail;
}
if (number <= (int) NPY_RAISE
@@ -664,61 +665,105 @@ PyArray_CastingConverter(PyObject *obj, NPY_CASTING *casting)
NPY_NO_EXPORT int
PyArray_PyIntAsInt(PyObject *o)
{
- long long_value = -1;
- PyObject *obj;
- static char *msg = "an integer is required";
- PyArrayObject *arr;
- PyArray_Descr *descr;
- int ret;
+ npy_intp long_value;
+ /* This assumes that NPY_SIZEOF_INTP >= NPY_SIZEOF_INT */
+ long_value = PyArray_PyIntAsIntp(o);
+#if (NPY_SIZEOF_INTP > NPY_SIZEOF_INT)
+ if ((long_value < INT_MIN) || (long_value > INT_MAX)) {
+ PyErr_SetString(PyExc_ValueError, "integer won't fit into a C int");
+ return -1;
+ }
+#endif
+ return (int) long_value;
+}
+
+/*NUMPY_API*/
+NPY_NO_EXPORT npy_intp
+PyArray_PyIntAsIntp(PyObject *o)
+{
+#if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP)
+ npy_long long_value = -1;
+#else
+ npy_longlong long_value = -1;
+#endif
+ PyObject *obj, *err;
+ static char *msg = "an integer is required";
if (!o) {
PyErr_SetString(PyExc_TypeError, msg);
return -1;
}
- if (PyInt_Check(o)) {
- long_value = (long) PyInt_AS_LONG(o);
- goto finish;
- } else if (PyLong_Check(o)) {
- long_value = (long) PyLong_AsLong(o);
- goto finish;
- }
- descr = &INT_Descr;
- arr = NULL;
- if (PyArray_Check(o)) {
- if (PyArray_SIZE((PyArrayObject *)o)!=1 ||
- !PyArray_ISINTEGER((PyArrayObject *)o)) {
- PyErr_SetString(PyExc_TypeError, msg);
+ /* Be a bit stricter and not allow bools */
+ if (PyBool_Check(o)) {
+ if (DEPRECATE("using a boolean instead of an integer"
+ " will result in an error in the future") < 0) {
return -1;
}
- Py_INCREF(descr);
- arr = (PyArrayObject *)PyArray_CastToType((PyArrayObject *)o,
- descr, 0);
}
- if (PyArray_IsScalar(o, Integer)) {
- Py_INCREF(descr);
- arr = (PyArrayObject *)PyArray_FromScalar(o, descr);
- }
- if (arr != NULL) {
- ret = *((int *)PyArray_DATA(arr));
- Py_DECREF(arr);
- return ret;
+
+ /*
+ * Since it is the usual case, first check if o is an integer. This is
+ * an exact check, since otherwise __index__ is used.
+ */
+#if !defined(NPY_PY3K)
+ if PyInt_CheckExact(o) {
+ #if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP)
+ long_value = (npy_longlong) PyInt_AsLong(o);
+ #else
+ long_value = PyInt_AsLong(o);
+ #endif
+ goto finish;
}
-#if (PY_VERSION_HEX >= 0x02050000)
- if (PyIndex_Check(o)) {
- PyObject* value = PyNumber_Index(o);
- long_value = (npy_longlong) PyInt_AsSsize_t(value);
+ else
+#endif
+ if PyLong_CheckExact(o) {
+#if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP)
+ long_value = PyLong_AsLongLong(o);
+#else
+ long_value = PyLong_AsLong(o);
+#endif
goto finish;
}
+ /*
+ * The most general case. PyNumber_Index(o) covers everything
+ * including arrays. In principle it may be possible to replace
+ * the whole function by PyIndex_AsSSize_t after deprecation.
+ */
+ obj = PyNumber_Index(o);
+ if (obj) {
+#if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP)
+ long_value = PyLong_AsLongLong(obj);
+#else
+ long_value = PyLong_AsLong(obj);
#endif
+ Py_DECREF(obj);
+ goto finish;
+ }
+ else {
+ /*
+ * Set the TypeError like PyNumber_Index(o) would after trying
+ * the general case.
+ */
+ PyErr_Clear();
+ }
+
+ /*
+ * For backward compatibility check the number C-Api number protcol
+ * This should be removed up the finish label after deprecation.
+ */
if (Py_TYPE(o)->tp_as_number != NULL &&
Py_TYPE(o)->tp_as_number->nb_int != NULL) {
obj = Py_TYPE(o)->tp_as_number->nb_int(o);
if (obj == NULL) {
return -1;
}
- long_value = (long) PyLong_AsLong(obj);
+ #if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP)
+ long_value = PyLong_AsLongLong(obj);
+ #else
+ long_value = PyLong_AsLong(obj);
+ #endif
Py_DECREF(obj);
}
#if !defined(NPY_PY3K)
@@ -728,126 +773,54 @@ PyArray_PyIntAsInt(PyObject *o)
if (obj == NULL) {
return -1;
}
- long_value = (long) PyLong_AsLong(obj);
+ #if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP)
+ long_value = PyLong_AsLongLong(obj);
+ #else
+ long_value = PyLong_AsLong(obj);
+ #endif
Py_DECREF(obj);
}
#endif
else {
- PyErr_SetString(PyExc_NotImplementedError,"");
- }
-
- finish:
- if error_converting(long_value) {
- PyErr_SetString(PyExc_TypeError, msg);
- return -1;
- }
-
-#if (NPY_SIZEOF_LONG > NPY_SIZEOF_INT)
- if ((long_value < INT_MIN) || (long_value > INT_MAX)) {
- PyErr_SetString(PyExc_ValueError, "integer won't fit into a C int");
- return -1;
- }
-#endif
- return (int) long_value;
-}
-
-/*NUMPY_API*/
-NPY_NO_EXPORT npy_intp
-PyArray_PyIntAsIntp(PyObject *o)
-{
- npy_longlong long_value = -1;
- PyObject *obj;
- static char *msg = "an integer is required";
- PyArrayObject *arr;
- PyArray_Descr *descr;
- npy_intp ret;
-
- if (!o) {
PyErr_SetString(PyExc_TypeError, msg);
return -1;
}
- if (PyInt_Check(o)) {
- long_value = (npy_longlong) PyInt_AS_LONG(o);
- goto finish;
- } else if (PyLong_Check(o)) {
- long_value = (npy_longlong) PyLong_AsLongLong(o);
- goto finish;
- }
-
-#if NPY_SIZEOF_INTP == NPY_SIZEOF_LONG
- descr = &LONG_Descr;
-#elif NPY_SIZEOF_INTP == NPY_SIZEOF_INT
- descr = &INT_Descr;
-#else
- descr = &LONGLONG_Descr;
-#endif
- arr = NULL;
-
- if (PyArray_Check(o)) {
- if (PyArray_SIZE((PyArrayObject *)o)!=1 ||
- !PyArray_ISINTEGER((PyArrayObject *)o)) {
- PyErr_SetString(PyExc_TypeError, msg);
+ /* Give a deprecation warning, unless there was already an error */
+ if (!error_converting(long_value)) {
+ if (DEPRECATE("using a non-integer number instead of an integer"
+ " will result in an error in the future") < 0) {
return -1;
}
- Py_INCREF(descr);
- arr = (PyArrayObject *)PyArray_CastToType((PyArrayObject *)o,
- descr, 0);
- }
- else if (PyArray_IsScalar(o, Integer)) {
- Py_INCREF(descr);
- arr = (PyArrayObject *)PyArray_FromScalar(o, descr);
- }
- if (arr != NULL) {
- ret = *((npy_intp *)PyArray_DATA(arr));
- Py_DECREF(arr);
- return ret;
- }
-
-#if (PY_VERSION_HEX >= 0x02050000)
- if (PyIndex_Check(o)) {
- PyObject* value = PyNumber_Index(o);
- if (value == NULL) {
- return -1;
- }
- long_value = (npy_longlong) PyInt_AsSsize_t(value);
- goto finish;
- }
-#endif
-#if !defined(NPY_PY3K)
- if (Py_TYPE(o)->tp_as_number != NULL && \
- Py_TYPE(o)->tp_as_number->nb_long != NULL) {
- obj = Py_TYPE(o)->tp_as_number->nb_long(o);
- if (obj != NULL) {
- long_value = (npy_longlong) PyLong_AsLongLong(obj);
- Py_DECREF(obj);
- }
- }
- else
-#endif
- if (Py_TYPE(o)->tp_as_number != NULL && \
- Py_TYPE(o)->tp_as_number->nb_int != NULL) {
- obj = Py_TYPE(o)->tp_as_number->nb_int(o);
- if (obj != NULL) {
- long_value = (npy_longlong) PyLong_AsLongLong(obj);
- Py_DECREF(obj);
- }
- }
- else {
- PyErr_SetString(PyExc_NotImplementedError,"");
}
finish:
- if error_converting(long_value) {
- PyErr_SetString(PyExc_TypeError, msg);
+ if (long_value == -1) {
+ err = PyErr_Occurred();
+ /* Only replace TypeError's here, which are the normal errors. */
+ if (err) {
+ if (PyErr_GivenExceptionMatches(err, PyExc_TypeError)) {
+ PyErr_SetString(PyExc_TypeError, msg);
+ }
return -1;
}
+ }
-#if (NPY_SIZEOF_LONGLONG > NPY_SIZEOF_INTP)
+#if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP)
+ #if (NPY_SIZEOF_LONGLONG > NPY_SIZEOF_INTP)
if ((long_value < NPY_MIN_INTP) || (long_value > NPY_MAX_INTP)) {
- PyErr_SetString(PyExc_ValueError,
- "integer won't fit into a C intp");
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert to C numpy.intp");
return -1;
}
+ #endif
+#else
+ #if (NPY_SIZEOF_LONG > NPY_SIZEOF_INTP)
+ if ((long_value < NPY_MIN_INTP) || (long_value > NPY_MAX_INTP)) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert to C numpy.intp");
+ return -1;
+ }
+ #endif
#endif
return (npy_intp) long_value;
}
@@ -867,29 +840,11 @@ PyArray_IntpFromSequence(PyObject *seq, npy_intp *vals, int maxvals)
* Check to see if sequence is a single integer first.
* or, can be made into one
*/
- if ((nd=PySequence_Length(seq)) == -1) {
+ nd = PySequence_Length(seq);
+ if (nd == -1) {
if (PyErr_Occurred()) PyErr_Clear();
-#if NPY_SIZEOF_LONG >= NPY_SIZEOF_INTP && !defined(NPY_PY3K)
- if (!(op = PyNumber_Int(seq))) {
- return -1;
- }
-#else
- if (!(op = PyNumber_Long(seq))) {
- return -1;
- }
-#endif
- nd = 1;
-#if NPY_SIZEOF_LONG >= NPY_SIZEOF_INTP
- vals[0] = (npy_intp ) PyInt_AsLong(op);
-#else
- vals[0] = (npy_intp ) PyLong_AsLongLong(op);
-#endif
- Py_DECREF(op);
- /*
- * Check wether there was an error - if the error was an overflow, raise
- * a ValueError instead to be more helpful
- */
+ vals[0] = PyArray_PyIntAsIntp(seq);
if(vals[0] == -1) {
err = PyErr_Occurred();
if (err &&
@@ -901,6 +856,7 @@ PyArray_IntpFromSequence(PyObject *seq, npy_intp *vals, int maxvals)
return -1;
}
}
+ nd = 1;
}
else {
for (i = 0; i < PyArray_MIN(nd,maxvals); i++) {
@@ -908,18 +864,10 @@ PyArray_IntpFromSequence(PyObject *seq, npy_intp *vals, int maxvals)
if (op == NULL) {
return -1;
}
-#if NPY_SIZEOF_LONG >= NPY_SIZEOF_INTP
- vals[i]=(npy_intp )PyInt_AsLong(op);
-#else
- vals[i]=(npy_intp )PyLong_AsLongLong(op);
-#endif
- Py_DECREF(op);
- /*
- * Check wether there was an error - if the error was an overflow,
- * raise a ValueError instead to be more helpful
- */
- if(vals[0] == -1) {
+
+ vals[i] = PyArray_PyIntAsIntp(op);
+ if(vals[i] == -1) {
err = PyErr_Occurred();
if (err &&
PyErr_GivenExceptionMatches(err, PyExc_OverflowError)) {