/*NUMPY_API * Convert an object to NPY_RAISE / NPY_CLIP / NPY_WRAP */ NPY_NO_EXPORT int PyArray_ClipmodeConverter(PyObject *object, NPY_CLIPMODE *val) { if (object == NULL || object == Py_None) { *val = NPY_RAISE; } else if (PyBytes_Check(object)) { char *str; str = PyBytes_AS_STRING(object); if (str[0] == 'C' || str[0] == 'c') { *val = NPY_CLIP; } else if (str[0] == 'W' || str[0] == 'w') { *val = NPY_WRAP; } else if (str[0] == 'R' || str[0] == 'r') { *val = NPY_RAISE; } else { PyErr_SetString(PyExc_TypeError, "clipmode not understood"); return NPY_FAIL; } } else if (PyUnicode_Check(object)) { PyObject *tmp; int ret; tmp = PyUnicode_AsASCIIString(object); if (tmp == NULL) { return NPY_FAIL; } ret = PyArray_ClipmodeConverter(tmp, val); Py_DECREF(tmp); return ret; } else { int number = PyArray_PyIntAsInt(object); if (error_converting(number)) { goto fail; } if (number <= (int) NPY_RAISE && number >= (int) NPY_CLIP) { *val = (NPY_CLIPMODE) number; } else { goto fail; } } return NPY_SUCCEED; fail: PyErr_SetString(PyExc_TypeError, "clipmode not understood"); return NPY_FAIL; }
/*NUMPY_API * Get axis from an object (possibly None) -- a converter function, * * See also PyArray_ConvertMultiAxis, which also handles a tuple of axes. */ NPY_NO_EXPORT int PyArray_AxisConverter(PyObject *obj, int *axis) { if (obj == Py_None) { *axis = NPY_MAXDIMS; } else { *axis = PyArray_PyIntAsInt_ErrMsg(obj, "an integer is required for the axis"); if (error_converting(*axis)) { return NPY_FAIL; } } return NPY_SUCCEED; }
/* * Extracts some values from the global pyvals tuple. * all destinations may be NULL, in which case they are not retrieved * ref - should hold the global tuple * name - is the name of the ufunc (ufuncobj->name) * * bufsize - receives the buffer size to use * errmask - receives the bitmask for error handling * errobj - receives the python object to call with the error, * if an error handling method is 'call' */ NPY_NO_EXPORT int _extract_pyvals(PyObject *ref, const char *name, int *bufsize, int *errmask, PyObject **errobj) { PyObject *retval; /* default errobj case, skips dictionary lookup */ if (ref == NULL) { if (errmask) { *errmask = UFUNC_ERR_DEFAULT; } if (errobj) { *errobj = Py_BuildValue("NO", PyBytes_FromString(name), Py_None); } if (bufsize) { *bufsize = NPY_BUFSIZE; } return 0; } if (!PyList_Check(ref) || (PyList_GET_SIZE(ref)!=3)) { PyErr_Format(PyExc_TypeError, "%s must be a length 3 list.", UFUNC_PYVALS_NAME); return -1; } if (bufsize != NULL) { *bufsize = PyInt_AsLong(PyList_GET_ITEM(ref, 0)); if (error_converting(*bufsize)) { return -1; } if ((*bufsize < NPY_MIN_BUFSIZE) || (*bufsize > NPY_MAX_BUFSIZE) || (*bufsize % 16 != 0)) { PyErr_Format(PyExc_ValueError, "buffer size (%d) is not in range " "(%"NPY_INTP_FMT" - %"NPY_INTP_FMT") or not a multiple of 16", *bufsize, (npy_intp) NPY_MIN_BUFSIZE, (npy_intp) NPY_MAX_BUFSIZE); return -1; } } if (errmask != NULL) { *errmask = PyInt_AsLong(PyList_GET_ITEM(ref, 1)); if (*errmask < 0) { if (PyErr_Occurred()) { return -1; } PyErr_Format(PyExc_ValueError, "invalid error mask (%d)", *errmask); return -1; } } if (errobj != NULL) { *errobj = NULL; retval = PyList_GET_ITEM(ref, 2); if (retval != Py_None && !PyCallable_Check(retval)) { PyObject *temp; temp = PyObject_GetAttrString(retval, "write"); if (temp == NULL || !PyCallable_Check(temp)) { PyErr_SetString(PyExc_TypeError, "python object must be callable or have " \ "a callable write method"); Py_XDECREF(temp); return -1; } Py_DECREF(temp); } *errobj = Py_BuildValue("NO", PyBytes_FromString(name), retval); if (*errobj == NULL) { return -1; } } return 0; }
/* * Fill in str with an appropriate PEP 3118 format string, based on * descr. For structured dtypes, calls itself recursively. Each call extends * str at offset then updates offset, and uses descr->byteorder, (and * possibly the byte order in obj) to determine the byte-order char. * * Returns 0 for success, -1 for failure */ static int _buffer_format_string(PyArray_Descr *descr, _tmp_string_t *str, PyObject* obj, Py_ssize_t *offset, char *active_byteorder) { int k; char _active_byteorder = '@'; Py_ssize_t _offset = 0; if (active_byteorder == NULL) { active_byteorder = &_active_byteorder; } if (offset == NULL) { offset = &_offset; } if (descr->subarray) { PyObject *item, *subarray_tuple; Py_ssize_t total_count = 1; Py_ssize_t dim_size; Py_ssize_t old_offset; char buf[128]; int ret; if (PyTuple_Check(descr->subarray->shape)) { subarray_tuple = descr->subarray->shape; Py_INCREF(subarray_tuple); } else { subarray_tuple = Py_BuildValue("(O)", descr->subarray->shape); } if (_append_char(str, '(') < 0) { ret = -1; goto subarray_fail; } for (k = 0; k < PyTuple_GET_SIZE(subarray_tuple); ++k) { if (k > 0) { if (_append_char(str, ',') < 0) { ret = -1; goto subarray_fail; } } item = PyTuple_GET_ITEM(subarray_tuple, k); dim_size = PyNumber_AsSsize_t(item, NULL); PyOS_snprintf(buf, sizeof(buf), "%ld", (long)dim_size); if (_append_str(str, buf) < 0) { ret = -1; goto subarray_fail; } total_count *= dim_size; } if (_append_char(str, ')') < 0) { ret = -1; goto subarray_fail; } old_offset = *offset; ret = _buffer_format_string(descr->subarray->base, str, obj, offset, active_byteorder); *offset = old_offset + (*offset - old_offset) * total_count; subarray_fail: Py_DECREF(subarray_tuple); return ret; } else if (PyDataType_HASFIELDS(descr)) { Py_ssize_t base_offset = *offset; if (_append_str(str, "T{") < 0) return -1; for (k = 0; k < PyTuple_GET_SIZE(descr->names); ++k) { PyObject *name, *item, *offset_obj; PyArray_Descr *child; Py_ssize_t new_offset; int ret; name = PyTuple_GET_ITEM(descr->names, k); item = PyDict_GetItem(descr->fields, name); child = (PyArray_Descr*)PyTuple_GetItem(item, 0); offset_obj = PyTuple_GetItem(item, 1); new_offset = PyInt_AsLong(offset_obj); if (error_converting(new_offset)) { return -1; } new_offset += base_offset; /* Insert padding manually */ if (*offset > new_offset) { PyErr_SetString( PyExc_ValueError, "dtypes with overlapping or out-of-order fields are not " "representable as buffers. Consider reordering the fields." ); return -1; } while (*offset < new_offset) { if (_append_char(str, 'x') < 0) return -1; ++*offset; } /* Insert child item */ ret = _buffer_format_string(child, str, obj, offset, active_byteorder); if (ret < 0) { return -1; } /* Insert field name */ if (_append_field_name(str, name) < 0) return -1; } if (_append_char(str, '}') < 0) return -1; } else { int is_standard_size = 1; int is_natively_aligned; int is_native_only_type = (descr->type_num == NPY_LONGDOUBLE || descr->type_num == NPY_CLONGDOUBLE); if (sizeof(npy_longlong) != 8) { is_native_only_type = is_native_only_type || ( descr->type_num == NPY_LONGLONG || descr->type_num == NPY_ULONGLONG); } *offset += descr->elsize; if (PyArray_IsScalar(obj, Generic)) { /* scalars are always natively aligned */ is_natively_aligned = 1; } else { is_natively_aligned = _is_natively_aligned_at(descr, (PyArrayObject*)obj, *offset); } if (descr->byteorder == '=' && is_natively_aligned) { /* Prefer native types, to cater for Cython */ is_standard_size = 0; if (*active_byteorder != '@') { if (_append_char(str, '@') < 0) return -1; *active_byteorder = '@'; } } else if (descr->byteorder == '=' && is_native_only_type) { /* Data types that have no standard size */ is_standard_size = 0; if (*active_byteorder != '^') { if (_append_char(str, '^') < 0) return -1; *active_byteorder = '^'; } } else if (descr->byteorder == '<' || descr->byteorder == '>' || descr->byteorder == '=') { is_standard_size = 1; if (*active_byteorder != descr->byteorder) { if (_append_char(str, descr->byteorder) < 0) return -1; *active_byteorder = descr->byteorder; } if (is_native_only_type) { /* * It's not possible to express native-only data types * in non-native npy_byte orders */ PyErr_Format(PyExc_ValueError, "cannot expose native-only dtype '%c' in " "non-native byte order '%c' via buffer interface", descr->type, descr->byteorder); return -1; } } switch (descr->type_num) { case NPY_BOOL: if (_append_char(str, '?') < 0) return -1; break; case NPY_BYTE: if (_append_char(str, 'b') < 0) return -1; break; case NPY_UBYTE: if (_append_char(str, 'B') < 0) return -1; break; case NPY_SHORT: if (_append_char(str, 'h') < 0) return -1; break; case NPY_USHORT: if (_append_char(str, 'H') < 0) return -1; break; case NPY_INT: if (_append_char(str, 'i') < 0) return -1; break; case NPY_UINT: if (_append_char(str, 'I') < 0) return -1; break; case NPY_LONG: if (is_standard_size && (NPY_SIZEOF_LONG == 8)) { if (_append_char(str, 'q') < 0) return -1; } else { if (_append_char(str, 'l') < 0) return -1; } break; case NPY_ULONG: if (is_standard_size && (NPY_SIZEOF_LONG == 8)) { if (_append_char(str, 'Q') < 0) return -1; } else { if (_append_char(str, 'L') < 0) return -1; } break; case NPY_LONGLONG: if (_append_char(str, 'q') < 0) return -1; break; case NPY_ULONGLONG: if (_append_char(str, 'Q') < 0) return -1; break; case NPY_HALF: if (_append_char(str, 'e') < 0) return -1; break; case NPY_FLOAT: if (_append_char(str, 'f') < 0) return -1; break; case NPY_DOUBLE: if (_append_char(str, 'd') < 0) return -1; break; case NPY_LONGDOUBLE: if (_append_char(str, 'g') < 0) return -1; break; case NPY_CFLOAT: if (_append_str(str, "Zf") < 0) return -1; break; case NPY_CDOUBLE: if (_append_str(str, "Zd") < 0) return -1; break; case NPY_CLONGDOUBLE: if (_append_str(str, "Zg") < 0) return -1; break; /* XXX NPY_DATETIME */ /* XXX NPY_TIMEDELTA */ case NPY_OBJECT: if (_append_char(str, 'O') < 0) return -1; break; case NPY_STRING: { char buf[128]; PyOS_snprintf(buf, sizeof(buf), "%ds", descr->elsize); if (_append_str(str, buf) < 0) return -1; break; } case NPY_UNICODE: { /* NumPy Unicode is always 4-byte */ char buf[128]; assert(descr->elsize % 4 == 0); PyOS_snprintf(buf, sizeof(buf), "%dw", descr->elsize / 4); if (_append_str(str, buf) < 0) return -1; break; } case NPY_VOID: { /* Insert padding bytes */ char buf[128]; PyOS_snprintf(buf, sizeof(buf), "%dx", descr->elsize); if (_append_str(str, buf) < 0) return -1; break; } default: PyErr_Format(PyExc_ValueError, "cannot include dtype '%c' in a buffer", descr->type); return -1; } } return 0; }
/* * Determine if object is a scalar and if so, convert the object * to a double and place it in the out_exponent argument * and return the "scalar kind" as a result. If the object is * not a scalar (or if there are other error conditions) * return NPY_NOSCALAR, and out_exponent is undefined. */ static NPY_SCALARKIND is_scalar_with_conversion(PyObject *o2, double* out_exponent) { PyObject *temp; const int optimize_fpexps = 1; if (PyInt_Check(o2)) { *out_exponent = (double)PyInt_AsLong(o2); return NPY_INTPOS_SCALAR; } if (optimize_fpexps && PyFloat_Check(o2)) { *out_exponent = PyFloat_AsDouble(o2); return NPY_FLOAT_SCALAR; } if (PyArray_Check(o2)) { if ((PyArray_NDIM((PyArrayObject *)o2) == 0) && ((PyArray_ISINTEGER((PyArrayObject *)o2) || (optimize_fpexps && PyArray_ISFLOAT((PyArrayObject *)o2))))) { temp = Py_TYPE(o2)->tp_as_number->nb_float(o2); if (temp == NULL) { return NPY_NOSCALAR; } *out_exponent = PyFloat_AsDouble(o2); Py_DECREF(temp); if (PyArray_ISINTEGER((PyArrayObject *)o2)) { return NPY_INTPOS_SCALAR; } else { /* ISFLOAT */ return NPY_FLOAT_SCALAR; } } } else if (PyArray_IsScalar(o2, Integer) || (optimize_fpexps && PyArray_IsScalar(o2, Floating))) { temp = Py_TYPE(o2)->tp_as_number->nb_float(o2); if (temp == NULL) { return NPY_NOSCALAR; } *out_exponent = PyFloat_AsDouble(o2); Py_DECREF(temp); if (PyArray_IsScalar(o2, Integer)) { return NPY_INTPOS_SCALAR; } else { /* IsScalar(o2, Floating) */ return NPY_FLOAT_SCALAR; } } else if (PyIndex_Check(o2)) { PyObject* value = PyNumber_Index(o2); Py_ssize_t val; if (value==NULL) { if (PyErr_Occurred()) { PyErr_Clear(); } return NPY_NOSCALAR; } val = PyInt_AsSsize_t(value); if (error_converting(val)) { PyErr_Clear(); return NPY_NOSCALAR; } *out_exponent = (double) val; return NPY_INTPOS_SCALAR; } return NPY_NOSCALAR; }
static npy_intp PyArray_PyIntAsIntp_ErrMsg(PyObject *o, const char * msg) { #if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP) long long long_value = -1; #else long long_value = -1; #endif PyObject *obj, *err; if (!o) { PyErr_SetString(PyExc_TypeError, msg); return -1; } /* Be a bit stricter and not allow bools, np.bool_ is handled later */ if (PyBool_Check(o)) { if (DEPRECATE("using a boolean instead of an integer" " will result in an error in the future") < 0) { return -1; } } /* * 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) /* No overflow is possible, so we can just return */ return PyInt_AS_LONG(o); #else long_value = PyInt_AS_LONG(o); goto overflow_check; #endif } 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 return (npy_intp)long_value; } /* Disallow numpy.bool_. Boolean arrays do not currently support index. */ if (PyArray_IsScalar(o, Bool)) { if (DEPRECATE("using a boolean instead of an integer" " will result in an error in the future") < 0) { return -1; } } /* * 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; } #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) else 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) { return -1; } #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_TypeError, msg); return -1; } /* 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; } } finish: if (error_converting(long_value)) { err = PyErr_Occurred(); /* Only replace TypeError's here, which are the normal errors. */ if (PyErr_GivenExceptionMatches(err, PyExc_TypeError)) { PyErr_SetString(PyExc_TypeError, msg); } return -1; } overflow_check: #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_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 long_value; }
/* * Converts an axis parameter into an ndim-length C-array of * boolean flags, True for each axis specified. * * If obj is None or NULL, everything is set to True. If obj is a tuple, * each axis within the tuple is set to True. If obj is an integer, * just that axis is set to True. */ NPY_NO_EXPORT int PyArray_ConvertMultiAxis(PyObject *axis_in, int ndim, npy_bool *out_axis_flags) { /* None means all of the axes */ if (axis_in == Py_None || axis_in == NULL) { memset(out_axis_flags, 1, ndim); return NPY_SUCCEED; } /* A tuple of which axes */ else if (PyTuple_Check(axis_in)) { int i, naxes; memset(out_axis_flags, 0, ndim); naxes = PyTuple_Size(axis_in); if (naxes < 0) { return NPY_FAIL; } for (i = 0; i < naxes; ++i) { PyObject *tmp = PyTuple_GET_ITEM(axis_in, i); int axis = PyArray_PyIntAsInt_ErrMsg(tmp, "integers are required for the axis tuple elements"); int axis_orig = axis; if (error_converting(axis)) { return NPY_FAIL; } if (axis < 0) { axis += ndim; } if (axis < 0 || axis >= ndim) { PyErr_Format(PyExc_ValueError, "'axis' entry %d is out of bounds [-%d, %d)", axis_orig, ndim, ndim); return NPY_FAIL; } if (out_axis_flags[axis]) { PyErr_SetString(PyExc_ValueError, "duplicate value in 'axis'"); return NPY_FAIL; } out_axis_flags[axis] = 1; } return NPY_SUCCEED; } /* Try to interpret axis as an integer */ else { int axis, axis_orig; memset(out_axis_flags, 0, ndim); axis = PyArray_PyIntAsInt_ErrMsg(axis_in, "an integer is required for the axis"); axis_orig = axis; if (error_converting(axis)) { return NPY_FAIL; } if (axis < 0) { axis += ndim; } /* * Special case letting axis={-1,0} slip through for scalars, * for backwards compatibility reasons. */ if (ndim == 0 && (axis == 0 || axis == -1)) { return NPY_SUCCEED; } if (axis < 0 || axis >= ndim) { PyErr_Format(PyExc_ValueError, "'axis' entry %d is out of bounds [-%d, %d)", axis_orig, ndim, ndim); return NPY_FAIL; } out_axis_flags[axis] = 1; return NPY_SUCCEED; } }
NPY_NO_EXPORT int PyArray_WeekMaskConverter(PyObject *weekmask_in, npy_bool *weekmask) { PyObject *obj = weekmask_in; /* Make obj into an ASCII string if it is UNICODE */ Py_INCREF(obj); if (PyUnicode_Check(obj)) { /* accept unicode input */ PyObject *obj_str; obj_str = PyUnicode_AsASCIIString(obj); if (obj_str == NULL) { Py_DECREF(obj); return 0; } Py_DECREF(obj); obj = obj_str; } if (PyBytes_Check(obj)) { char *str; Py_ssize_t len; int i; if (PyBytes_AsStringAndSize(obj, &str, &len) < 0) { Py_DECREF(obj); return 0; } /* Length 7 is a string like "1111100" */ if (len == 7) { for (i = 0; i < 7; ++i) { switch(str[i]) { case '0': weekmask[i] = 0; break; case '1': weekmask[i] = 1; break; default: goto general_weekmask_string; } } goto finish; } general_weekmask_string: /* a string like "SatSun" or "Mon Tue Wed" */ memset(weekmask, 0, 7); for (i = 0; i < len; i += 3) { while (isspace(str[i])) ++i; if (i == len) { goto finish; } else if (i + 2 >= len) { goto invalid_weekmask_string; } switch (str[i]) { case 'M': if (str[i+1] == 'o' && str[i+2] == 'n') { weekmask[0] = 1; } else { goto invalid_weekmask_string; } break; case 'T': if (str[i+1] == 'u' && str[i+2] == 'e') { weekmask[1] = 1; } else if (str[i+1] == 'h' && str[i+2] == 'u') { weekmask[3] = 1; } else { goto invalid_weekmask_string; } break; case 'W': if (str[i+1] == 'e' && str[i+2] == 'd') { weekmask[2] = 1; } else { goto invalid_weekmask_string; } break; case 'F': if (str[i+1] == 'r' && str[i+2] == 'i') { weekmask[4] = 1; } else { goto invalid_weekmask_string; } break; case 'S': if (str[i+1] == 'a' && str[i+2] == 't') { weekmask[5] = 1; } else if (str[i+1] == 'u' && str[i+2] == 'n') { weekmask[6] = 1; } else { goto invalid_weekmask_string; } break; default: goto invalid_weekmask_string; } } goto finish; invalid_weekmask_string: PyErr_Format(PyExc_ValueError, "Invalid business day weekmask string \"%s\"", str); Py_DECREF(obj); return 0; } /* Something like [1,1,1,1,1,0,0] */ else if (PySequence_Check(obj)) { if (PySequence_Size(obj) != 7 || (PyArray_Check(obj) && PyArray_NDIM((PyArrayObject *)obj) != 1)) { PyErr_SetString(PyExc_ValueError, "A business day weekmask array must have length 7"); Py_DECREF(obj); return 0; } else { int i; for (i = 0; i < 7; ++i) { long val; PyObject *f = PySequence_GetItem(obj, i); if (f == NULL) { Py_DECREF(obj); return 0; } val = PyInt_AsLong(f); if (error_converting(val)) { Py_DECREF(f); Py_DECREF(obj); return 0; } if (val == 0) { weekmask[i] = 0; } else if (val == 1) { weekmask[i] = 1; } else { PyErr_SetString(PyExc_ValueError, "A business day weekmask array must have all " "1's and 0's"); Py_DECREF(f); Py_DECREF(obj); return 0; } Py_DECREF(f); } goto finish; } } PyErr_SetString(PyExc_ValueError, "Couldn't convert object into a business day weekmask"); Py_DECREF(obj); return 0; finish: Py_DECREF(obj); return 1; }
static npy_intp PyArray_PyIntAsIntp_ErrMsg(PyObject *o, const char * msg) { #if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP) long long long_value = -1; #else long long_value = -1; #endif PyObject *obj, *err; /* * Be a bit stricter and not allow bools. * np.bool_ is also disallowed as Boolean arrays do not currently * support index. */ if (!o || PyBool_Check(o) || PyArray_IsScalar(o, Bool)) { PyErr_SetString(PyExc_TypeError, msg); return -1; } /* * 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) /* No overflow is possible, so we can just return */ return PyInt_AS_LONG(o); #else long_value = PyInt_AS_LONG(o); goto overflow_check; #endif } 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 return (npy_intp)long_value; } /* * 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 == NULL) { return -1; } #if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP) long_value = PyLong_AsLongLong(obj); #else long_value = PyLong_AsLong(obj); #endif Py_DECREF(obj); if (error_converting(long_value)) { err = PyErr_Occurred(); /* Only replace TypeError's here, which are the normal errors. */ if (PyErr_GivenExceptionMatches(err, PyExc_TypeError)) { PyErr_SetString(PyExc_TypeError, msg); } return -1; } goto overflow_check; /* silence unused warning */ overflow_check: #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_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 long_value; }