Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
| /* -*- c -*- */ | |
| #define PY_SSIZE_T_CLEAN | |
| #include "Python.h" | |
| #include "structmember.h" | |
| #define NPY_NO_DEPRECATED_API NPY_API_VERSION | |
| #ifndef _MULTIARRAYMODULE | |
| #define _MULTIARRAYMODULE | |
| #endif | |
| #include "numpy/arrayobject.h" | |
| #include "numpy/npy_math.h" | |
| #include "numpy/halffloat.h" | |
| #include "numpy/arrayscalars.h" | |
| #include "npy_pycompat.h" | |
| #include "npy_config.h" | |
| #include "mapping.h" | |
| #include "ctors.h" | |
| #include "usertypes.h" | |
| #include "numpyos.h" | |
| #include "common.h" | |
| #include "scalartypes.h" | |
| #include "_datetime.h" | |
| #include "datetime_strings.h" | |
| #include "alloc.h" | |
| #include "npy_import.h" | |
| #include "dragon4.h" | |
| #include "npy_longdouble.h" | |
| #include "buffer.h" | |
| #include <stdlib.h> | |
| #include "binop_override.h" | |
| NPY_NO_EXPORT PyBoolScalarObject _PyArrayScalar_BoolValues[] = { | |
| {PyObject_HEAD_INIT(&PyBoolArrType_Type) 0}, | |
| {PyObject_HEAD_INIT(&PyBoolArrType_Type) 1}, | |
| }; | |
| /* TimeInteger is deleted, but still here to fill the API slot */ | |
| NPY_NO_EXPORT PyTypeObject PyTimeIntegerArrType_Type; | |
| /* | |
| * Inheritance is established later when tp_bases is set (or tp_base for | |
| * single inheritance) | |
| */ | |
| /**begin repeat | |
| * #name = number, integer, signedinteger, unsignedinteger, inexact, | |
| * floating, complexfloating, flexible, character# | |
| * #NAME = Number, Integer, SignedInteger, UnsignedInteger, Inexact, | |
| * Floating, ComplexFloating, Flexible, Character# | |
| */ | |
| NPY_NO_EXPORT PyTypeObject Py@NAME@ArrType_Type = { | |
| #if defined(NPY_PY3K) | |
| PyVarObject_HEAD_INIT(NULL, 0) | |
| #else | |
| PyObject_HEAD_INIT(NULL) | |
| 0, /* ob_size */ | |
| #endif | |
| "numpy.@name@", /* tp_name*/ | |
| sizeof(PyObject), /* tp_basicsize*/ | |
| 0, /* tp_itemsize */ | |
| /* methods */ | |
| 0, /* tp_dealloc */ | |
| 0, /* tp_print */ | |
| 0, /* tp_getattr */ | |
| 0, /* tp_setattr */ | |
| #if defined(NPY_PY3K) | |
| 0, /* tp_reserved */ | |
| #else | |
| 0, /* tp_compare */ | |
| #endif | |
| 0, /* tp_repr */ | |
| 0, /* tp_as_number */ | |
| 0, /* tp_as_sequence */ | |
| 0, /* tp_as_mapping */ | |
| 0, /* tp_hash */ | |
| 0, /* tp_call */ | |
| 0, /* tp_str */ | |
| 0, /* tp_getattro */ | |
| 0, /* tp_setattro */ | |
| 0, /* tp_as_buffer */ | |
| 0, /* tp_flags */ | |
| 0, /* tp_doc */ | |
| 0, /* tp_traverse */ | |
| 0, /* tp_clear */ | |
| 0, /* tp_richcompare */ | |
| 0, /* tp_weaklistoffset */ | |
| 0, /* tp_iter */ | |
| 0, /* tp_iternext */ | |
| 0, /* tp_methods */ | |
| 0, /* tp_members */ | |
| 0, /* tp_getset */ | |
| 0, /* tp_base */ | |
| 0, /* tp_dict */ | |
| 0, /* tp_descr_get */ | |
| 0, /* tp_descr_set */ | |
| 0, /* tp_dictoffset */ | |
| 0, /* tp_init */ | |
| 0, /* tp_alloc */ | |
| 0, /* tp_new */ | |
| 0, /* tp_free */ | |
| 0, /* tp_is_gc */ | |
| 0, /* tp_bases */ | |
| 0, /* tp_mro */ | |
| 0, /* tp_cache */ | |
| 0, /* tp_subclasses */ | |
| 0, /* tp_weaklist */ | |
| 0, /* tp_del */ | |
| 0, /* tp_version_tag */ | |
| }; | |
| /**end repeat**/ | |
| static PyObject * | |
| gentype_alloc(PyTypeObject *type, Py_ssize_t nitems) | |
| { | |
| PyObject *obj; | |
| const size_t size = _PyObject_VAR_SIZE(type, nitems + 1); | |
| obj = (PyObject *)PyObject_Malloc(size); | |
| /* | |
| * Fixme. Need to check for no memory. | |
| * If we don't need to zero memory, we could use | |
| * PyObject_{New, NewVar} for this whole function. | |
| */ | |
| memset(obj, 0, size); | |
| if (type->tp_itemsize == 0) { | |
| PyObject_Init(obj, type); | |
| } | |
| else { | |
| (void) PyObject_InitVar((PyVarObject *)obj, type, nitems); | |
| } | |
| return obj; | |
| } | |
| static void | |
| gentype_dealloc(PyObject *v) | |
| { | |
| Py_TYPE(v)->tp_free(v); | |
| } | |
| static void | |
| gentype_free(PyObject *v) | |
| { | |
| /* | |
| * have an explicit tp_free to enforce inheritance from it. | |
| * PyObject_Free is also the tp_free of PyBaseObject so python does not | |
| * COPYSLOT it, instead it takes the next parent PyInt which has a | |
| * different allocator | |
| */ | |
| PyObject_Free(v); | |
| } | |
| static PyObject * | |
| gentype_power(PyObject *m1, PyObject *m2, PyObject *modulo) | |
| { | |
| if (modulo != Py_None) { | |
| /* modular exponentiation is not implemented (gh-8804) */ | |
| Py_INCREF(Py_NotImplemented); | |
| return Py_NotImplemented; | |
| } | |
| BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_power, gentype_power); | |
| return PyArray_Type.tp_as_number->nb_power(m1, m2, Py_None); | |
| } | |
| static PyObject * | |
| gentype_generic_method(PyObject *self, PyObject *args, PyObject *kwds, | |
| char *str) | |
| { | |
| PyObject *arr, *meth, *ret; | |
| arr = PyArray_FromScalar(self, NULL); | |
| if (arr == NULL) { | |
| return NULL; | |
| } | |
| meth = PyObject_GetAttrString(arr, str); | |
| if (meth == NULL) { | |
| Py_DECREF(arr); | |
| return NULL; | |
| } | |
| if (kwds == NULL) { | |
| ret = PyObject_CallObject(meth, args); | |
| } | |
| else { | |
| ret = PyObject_Call(meth, args, kwds); | |
| } | |
| Py_DECREF(meth); | |
| Py_DECREF(arr); | |
| if (ret && PyArray_Check(ret)) { | |
| return PyArray_Return((PyArrayObject *)ret); | |
| } | |
| else { | |
| return ret; | |
| } | |
| } | |
| static PyObject * | |
| gentype_add(PyObject *m1, PyObject* m2) | |
| { | |
| /* special case str.__radd__, which should not call array_add */ | |
| if (PyString_Check(m1) || PyUnicode_Check(m1)) { | |
| Py_INCREF(Py_NotImplemented); | |
| return Py_NotImplemented; | |
| } | |
| BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_add, gentype_add); | |
| return PyArray_Type.tp_as_number->nb_add(m1, m2); | |
| } | |
| /**begin repeat | |
| * | |
| * #name = subtract, remainder, divmod, lshift, rshift, | |
| * and, xor, or, floor_divide, true_divide# | |
| */ | |
| static PyObject * | |
| gentype_@name@(PyObject *m1, PyObject *m2) | |
| { | |
| BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_@name@, gentype_@name@); | |
| return PyArray_Type.tp_as_number->nb_@name@(m1, m2); | |
| } | |
| /**end repeat**/ | |
| #if !defined(NPY_PY3K) | |
| /**begin repeat | |
| * | |
| * #name = divide# | |
| */ | |
| static PyObject * | |
| gentype_@name@(PyObject *m1, PyObject *m2) | |
| { | |
| BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_@name@, gentype_@name@); | |
| return PyArray_Type.tp_as_number->nb_@name@(m1, m2); | |
| } | |
| /**end repeat**/ | |
| #endif | |
| /* Get a nested slot, or NULL if absent */ | |
| #define GET_NESTED_SLOT(type, group, slot) \ | |
| ((type)->group == NULL ? NULL : (type)->group->slot) | |
| static PyObject * | |
| gentype_multiply(PyObject *m1, PyObject *m2) | |
| { | |
| /* | |
| * If the other object supports sequence repeat and not number multiply | |
| * we fall back on the python builtin to invoke the sequence repeat, rather | |
| * than promoting both arguments to ndarray. | |
| * This covers a list repeat by numpy scalars. | |
| * A python defined class will always only have the nb_multiply slot and | |
| * some classes may have neither defined. For the latter we want need | |
| * to give the normal case a chance to convert the object to ndarray. | |
| * Probably no class has both defined, but if they do, prefer number. | |
| */ | |
| if (!PyArray_IsScalar(m1, Generic) && | |
| GET_NESTED_SLOT(Py_TYPE(m1), tp_as_sequence, sq_repeat) != NULL && | |
| GET_NESTED_SLOT(Py_TYPE(m1), tp_as_number, nb_multiply) == NULL) { | |
| Py_INCREF(Py_NotImplemented); | |
| return Py_NotImplemented; | |
| } | |
| if (!PyArray_IsScalar(m2, Generic) && | |
| GET_NESTED_SLOT(Py_TYPE(m2), tp_as_sequence, sq_repeat) != NULL && | |
| GET_NESTED_SLOT(Py_TYPE(m2), tp_as_number, nb_multiply) == NULL) { | |
| Py_INCREF(Py_NotImplemented); | |
| return Py_NotImplemented; | |
| } | |
| /* All normal cases are handled by PyArray's multiply */ | |
| BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_multiply, gentype_multiply); | |
| return PyArray_Type.tp_as_number->nb_multiply(m1, m2); | |
| } | |
| /**begin repeat | |
| * | |
| * #name = positive, negative, absolute, invert, int, float# | |
| */ | |
| static PyObject * | |
| gentype_@name@(PyObject *m1) | |
| { | |
| PyObject *arr, *ret; | |
| arr = PyArray_FromScalar(m1, NULL); | |
| if (arr == NULL) { | |
| return NULL; | |
| } | |
| ret = Py_TYPE(arr)->tp_as_number->nb_@name@(arr); | |
| Py_DECREF(arr); | |
| return ret; | |
| } | |
| /**end repeat**/ | |
| #if !defined(NPY_PY3K) | |
| /**begin repeat | |
| * | |
| * #name = long, oct, hex# | |
| */ | |
| static PyObject * | |
| gentype_@name@(PyObject *m1) | |
| { | |
| PyObject *arr, *ret; | |
| arr = PyArray_FromScalar(m1, NULL); | |
| if (arr == NULL) { | |
| return NULL; | |
| } | |
| ret = Py_TYPE(arr)->tp_as_number->nb_@name@(arr); | |
| Py_DECREF(arr); | |
| return ret; | |
| } | |
| /**end repeat**/ | |
| #endif | |
| static int | |
| gentype_nonzero_number(PyObject *m1) | |
| { | |
| PyObject *arr; | |
| int ret; | |
| arr = PyArray_FromScalar(m1, NULL); | |
| if (arr == NULL) { | |
| return -1; | |
| } | |
| #if defined(NPY_PY3K) | |
| ret = Py_TYPE(arr)->tp_as_number->nb_bool(arr); | |
| #else | |
| ret = Py_TYPE(arr)->tp_as_number->nb_nonzero(arr); | |
| #endif | |
| Py_DECREF(arr); | |
| return ret; | |
| } | |
| static PyObject * | |
| genint_type_str(PyObject *self) | |
| { | |
| PyObject *item, *item_str; | |
| item = gentype_generic_method(self, NULL, NULL, "item"); | |
| if (item == NULL) { | |
| return NULL; | |
| } | |
| item_str = PyObject_Str(item); | |
| Py_DECREF(item); | |
| return item_str; | |
| } | |
| /* | |
| * The __format__ method for PEP 3101. | |
| */ | |
| static PyObject * | |
| gentype_format(PyObject *self, PyObject *args) | |
| { | |
| PyObject *format_spec; | |
| PyObject *obj, *ret; | |
| #if defined(NPY_PY3K) | |
| if (!PyArg_ParseTuple(args, "U:__format__", &format_spec)) { | |
| return NULL; | |
| } | |
| #else | |
| if (!PyArg_ParseTuple(args, "O:__format__", &format_spec)) { | |
| return NULL; | |
| } | |
| if (!PyUnicode_Check(format_spec) && !PyString_Check(format_spec)) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "format must be a string"); | |
| return NULL; | |
| } | |
| #endif | |
| /* | |
| * Convert to an appropriate Python type and call its format. | |
| * TODO: For some types, like long double, this isn't right, | |
| * because it throws away precision. | |
| */ | |
| if (Py_TYPE(self) == &PyBoolArrType_Type) { | |
| obj = PyBool_FromLong(((PyBoolScalarObject *)self)->obval); | |
| } | |
| else if (PyArray_IsScalar(self, Integer)) { | |
| #if defined(NPY_PY3K) | |
| obj = Py_TYPE(self)->tp_as_number->nb_int(self); | |
| #else | |
| obj = Py_TYPE(self)->tp_as_number->nb_long(self); | |
| #endif | |
| } | |
| else if (PyArray_IsScalar(self, Floating)) { | |
| obj = Py_TYPE(self)->tp_as_number->nb_float(self); | |
| } | |
| else if (PyArray_IsScalar(self, ComplexFloating)) { | |
| double val[2]; | |
| PyArray_Descr *dtype = PyArray_DescrFromScalar(self); | |
| if (dtype == NULL) { | |
| return NULL; | |
| } | |
| if (PyArray_CastScalarDirect(self, dtype, &val[0], NPY_CDOUBLE) < 0) { | |
| Py_DECREF(dtype); | |
| return NULL; | |
| } | |
| obj = PyComplex_FromDoubles(val[0], val[1]); | |
| Py_DECREF(dtype); | |
| } | |
| else { | |
| obj = PyObject_Str(self); | |
| } | |
| if (obj == NULL) { | |
| return NULL; | |
| } | |
| ret = PyObject_Format(obj, format_spec); | |
| Py_DECREF(obj); | |
| return ret; | |
| } | |
| #ifdef FORCE_NO_LONG_DOUBLE_FORMATTING | |
| #undef NPY_LONGDOUBLE_FMT | |
| #define NPY_LONGDOUBLE_FMT NPY_DOUBLE_FMT | |
| #endif | |
| /**begin repeat | |
| * #name = half, float, double, longdouble# | |
| * #Name = Half, Float, Double, LongDouble# | |
| * #NAME = HALF, FLOAT, DOUBLE, LONGDOUBLE# | |
| * #type = npy_half, npy_float, npy_double, npy_longdouble# | |
| * #suff = h, f, d, l# | |
| */ | |
| NPY_NO_EXPORT PyObject * | |
| format_@name@(@type@ val, npy_bool scientific, | |
| int precision, int sign, TrimMode trim, | |
| int pad_left, int pad_right, int exp_digits) | |
| { | |
| if (scientific) { | |
| return Dragon4_Scientific_@Name@(&val, | |
| DigitMode_Unique, precision, | |
| sign, trim, pad_left, exp_digits); | |
| } | |
| else { | |
| return Dragon4_Positional_@Name@(&val, | |
| DigitMode_Unique, CutoffMode_TotalLength, precision, | |
| sign, trim, pad_left, pad_right); | |
| } | |
| } | |
| /**end repeat**/ | |
| /* | |
| * over-ride repr and str of array-scalar strings and unicode to | |
| * remove NULL bytes and then call the corresponding functions | |
| * of string and unicode. | |
| */ | |
| /**begin repeat | |
| * #name = string*2,unicode*2# | |
| * #form = (repr,str)*2# | |
| * #Name = String*2,Unicode*2# | |
| * #NAME = STRING*2,UNICODE*2# | |
| * #extra = AndSize*2,,# | |
| * #type = npy_char*2, Py_UNICODE*2# | |
| */ | |
| static PyObject * | |
| @name@type_@form@(PyObject *self) | |
| { | |
| const @type@ *dptr, *ip; | |
| int len; | |
| PyObject *new; | |
| PyObject *ret; | |
| ip = dptr = Py@Name@_AS_@NAME@(self); | |
| len = Py@Name@_GET_SIZE(self); | |
| dptr += len-1; | |
| while(len > 0 && *dptr-- == 0) { | |
| len--; | |
| } | |
| new = Py@Name@_From@Name@@extra@(ip, len); | |
| if (new == NULL) { | |
| return PyUString_FromString(""); | |
| } | |
| ret = Py@Name@_Type.tp_@form@(new); | |
| Py_DECREF(new); | |
| return ret; | |
| } | |
| /**end repeat**/ | |
| /* | |
| * Convert array of bytes to a string representation much like bytes.__repr__, | |
| * but convert all bytes (including ASCII) to the `\x00` notation with | |
| * uppercase hex codes (FF not ff). | |
| * | |
| * Largely copied from _Py_strhex_impl in CPython implementation | |
| */ | |
| static NPY_INLINE PyObject * | |
| _void_to_hex(const char* argbuf, const Py_ssize_t arglen, | |
| const char *schars, const char *bprefix, const char *echars) | |
| { | |
| PyObject *retval; | |
| int extrachars, slen; | |
| char *retbuf; | |
| Py_ssize_t i, j; | |
| char const *hexdigits = "0123456789ABCDEF"; | |
| extrachars = strlen(schars) + strlen(echars); | |
| slen = extrachars + arglen*(2 + strlen(bprefix)); | |
| if (arglen > (PY_SSIZE_T_MAX / 2) - extrachars) { | |
| return PyErr_NoMemory(); | |
| } | |
| retbuf = (char *)PyMem_Malloc(slen); | |
| if (!retbuf) { | |
| return PyErr_NoMemory(); | |
| } | |
| memcpy(retbuf, schars, strlen(schars)); | |
| j = strlen(schars); | |
| for (i = 0; i < arglen; i++) { | |
| unsigned char c; | |
| memcpy(&retbuf[j], bprefix, strlen(bprefix)); | |
| j += strlen(bprefix); | |
| c = (argbuf[i] >> 4) & 0xf; | |
| retbuf[j++] = hexdigits[c]; | |
| c = argbuf[i] & 0xf; | |
| retbuf[j++] = hexdigits[c]; | |
| } | |
| memcpy(&retbuf[j], echars, strlen(echars)); | |
| retval = PyUString_FromStringAndSize(retbuf, slen); | |
| PyMem_Free(retbuf); | |
| return retval; | |
| } | |
| static PyObject * | |
| _void_scalar_repr(PyObject *obj) { | |
| static PyObject *reprfunc = NULL; | |
| npy_cache_import("numpy.core.arrayprint", | |
| "_void_scalar_repr", &reprfunc); | |
| if (reprfunc == NULL) { | |
| return NULL; | |
| } | |
| return PyObject_CallFunction(reprfunc, "O", obj); | |
| } | |
| static PyObject * | |
| voidtype_repr(PyObject *self) | |
| { | |
| PyVoidScalarObject *s = (PyVoidScalarObject*) self; | |
| if (PyDataType_HASFIELDS(s->descr)) { | |
| return _void_scalar_repr(self); | |
| } | |
| return _void_to_hex(s->obval, s->descr->elsize, "void(b'", "\\x", "')"); | |
| } | |
| static PyObject * | |
| voidtype_str(PyObject *self) | |
| { | |
| PyVoidScalarObject *s = (PyVoidScalarObject*) self; | |
| if (PyDataType_HASFIELDS(s->descr)) { | |
| return _void_scalar_repr(self); | |
| } | |
| return _void_to_hex(s->obval, s->descr->elsize, "b'", "\\x", "'"); | |
| } | |
| static PyObject * | |
| datetimetype_repr(PyObject *self) | |
| { | |
| PyDatetimeScalarObject *scal; | |
| npy_datetimestruct dts; | |
| PyObject *ret; | |
| char iso[NPY_DATETIME_MAX_ISO8601_STRLEN]; | |
| NPY_DATETIMEUNIT unit; | |
| if (!PyArray_IsScalar(self, Datetime)) { | |
| PyErr_SetString(PyExc_RuntimeError, | |
| "Called NumPy datetime repr on a non-datetime type"); | |
| return NULL; | |
| } | |
| scal = (PyDatetimeScalarObject *)self; | |
| if (convert_datetime_to_datetimestruct(&scal->obmeta, | |
| scal->obval, &dts) < 0) { | |
| return NULL; | |
| } | |
| unit = scal->obmeta.base; | |
| if (make_iso_8601_datetime(&dts, iso, sizeof(iso), 0, 0, | |
| unit, -1, NPY_SAFE_CASTING) < 0) { | |
| return NULL; | |
| } | |
| /* | |
| * For straight units or generic units, the unit will be deduced | |
| * from the string, so it's not necessary to specify it. | |
| */ | |
| if ((scal->obmeta.num == 1 && scal->obmeta.base != NPY_FR_h) || | |
| scal->obmeta.base == NPY_FR_GENERIC) { | |
| ret = PyUString_FromString("numpy.datetime64('"); | |
| PyUString_ConcatAndDel(&ret, | |
| PyUString_FromString(iso)); | |
| PyUString_ConcatAndDel(&ret, | |
| PyUString_FromString("')")); | |
| } | |
| else { | |
| ret = PyUString_FromString("numpy.datetime64('"); | |
| PyUString_ConcatAndDel(&ret, | |
| PyUString_FromString(iso)); | |
| PyUString_ConcatAndDel(&ret, | |
| PyUString_FromString("','")); | |
| ret = append_metastr_to_string(&scal->obmeta, 1, ret); | |
| PyUString_ConcatAndDel(&ret, | |
| PyUString_FromString("')")); | |
| } | |
| return ret; | |
| } | |
| static PyObject * | |
| timedeltatype_repr(PyObject *self) | |
| { | |
| PyTimedeltaScalarObject *scal; | |
| PyObject *ret; | |
| if (!PyArray_IsScalar(self, Timedelta)) { | |
| PyErr_SetString(PyExc_RuntimeError, | |
| "Called NumPy timedelta repr on a non-datetime type"); | |
| return NULL; | |
| } | |
| scal = (PyTimedeltaScalarObject *)self; | |
| /* The value */ | |
| if (scal->obval == NPY_DATETIME_NAT) { | |
| ret = PyUString_FromString("numpy.timedelta64('NaT'"); | |
| } | |
| else { | |
| /* | |
| * Can't use "%lld" if HAVE_LONG_LONG is not defined | |
| */ | |
| #if defined(HAVE_LONG_LONG) | |
| ret = PyUString_FromFormat("numpy.timedelta64(%lld", | |
| (long long)scal->obval); | |
| #else | |
| ret = PyUString_FromFormat("numpy.timedelta64(%ld", | |
| (long)scal->obval); | |
| #endif | |
| } | |
| /* The metadata unit */ | |
| if (scal->obmeta.base == NPY_FR_GENERIC) { | |
| PyUString_ConcatAndDel(&ret, | |
| PyUString_FromString(")")); | |
| } | |
| else { | |
| PyUString_ConcatAndDel(&ret, | |
| PyUString_FromString(",'")); | |
| ret = append_metastr_to_string(&scal->obmeta, 1, ret); | |
| PyUString_ConcatAndDel(&ret, | |
| PyUString_FromString("')")); | |
| } | |
| return ret; | |
| } | |
| static PyObject * | |
| datetimetype_str(PyObject *self) | |
| { | |
| PyDatetimeScalarObject *scal; | |
| npy_datetimestruct dts; | |
| char iso[NPY_DATETIME_MAX_ISO8601_STRLEN]; | |
| NPY_DATETIMEUNIT unit; | |
| if (!PyArray_IsScalar(self, Datetime)) { | |
| PyErr_SetString(PyExc_RuntimeError, | |
| "Called NumPy datetime str on a non-datetime type"); | |
| return NULL; | |
| } | |
| scal = (PyDatetimeScalarObject *)self; | |
| if (convert_datetime_to_datetimestruct(&scal->obmeta, scal->obval, | |
| &dts) < 0) { | |
| return NULL; | |
| } | |
| unit = scal->obmeta.base; | |
| if (make_iso_8601_datetime(&dts, iso, sizeof(iso), 0, 0, | |
| unit, -1, NPY_SAFE_CASTING) < 0) { | |
| return NULL; | |
| } | |
| return PyUString_FromString(iso); | |
| } | |
| static char *_datetime_verbose_strings[NPY_DATETIME_NUMUNITS] = { | |
| "years", | |
| "months", | |
| "weeks", | |
| "<invalid>", | |
| "days", | |
| "hours", | |
| "minutes", | |
| "seconds", | |
| "milliseconds", | |
| "microseconds", | |
| "nanoseconds", | |
| "picoseconds", | |
| "femtoseconds", | |
| "attoseconds", | |
| "generic time units" | |
| }; | |
| static PyObject * | |
| timedeltatype_str(PyObject *self) | |
| { | |
| PyTimedeltaScalarObject *scal; | |
| PyObject *ret; | |
| char *basestr = "invalid"; | |
| if (!PyArray_IsScalar(self, Timedelta)) { | |
| PyErr_SetString(PyExc_RuntimeError, | |
| "Called NumPy timedelta str on a non-datetime type"); | |
| return NULL; | |
| } | |
| scal = (PyTimedeltaScalarObject *)self; | |
| if (scal->obmeta.base >= 0 && scal->obmeta.base < NPY_DATETIME_NUMUNITS) { | |
| basestr = _datetime_verbose_strings[scal->obmeta.base]; | |
| } | |
| else { | |
| PyErr_SetString(PyExc_RuntimeError, | |
| "NumPy datetime metadata is corrupted"); | |
| return NULL; | |
| } | |
| if (scal->obval == NPY_DATETIME_NAT) { | |
| ret = PyUString_FromString("NaT"); | |
| } | |
| else { | |
| /* | |
| * Can't use "%lld" if HAVE_LONG_LONG is not defined | |
| */ | |
| #if defined(HAVE_LONG_LONG) | |
| ret = PyUString_FromFormat("%lld ", | |
| (long long)(scal->obval * scal->obmeta.num)); | |
| #else | |
| ret = PyUString_FromFormat("%ld ", | |
| (long)(scal->obval * scal->obmeta.num)); | |
| #endif | |
| PyUString_ConcatAndDel(&ret, | |
| PyUString_FromString(basestr)); | |
| } | |
| return ret; | |
| } | |
| /* | |
| * float type str and repr | |
| * | |
| * These functions will return NULL if PyString creation fails. | |
| */ | |
| /* | |
| * *** BEGIN LEGACY PRINTING MODE CODE *** | |
| * | |
| * This code is legacy code needed to reproduce the printing behavior of | |
| * scalars in numpy 1.13. One day we hope to remove it. | |
| */ | |
| /* determines if legacy mode is enabled, global set in multiarraymodule.c */ | |
| extern int npy_legacy_print_mode; | |
| #define HALFPREC_REPR 5 | |
| #define HALFPREC_STR 5 | |
| #define FLOATPREC_REPR 8 | |
| #define FLOATPREC_STR 6 | |
| #define DOUBLEPREC_REPR 17 | |
| #define DOUBLEPREC_STR 12 | |
| #if NPY_SIZEOF_LONGDOUBLE == NPY_SIZEOF_DOUBLE | |
| #define LONGDOUBLEPREC_REPR DOUBLEPREC_REPR | |
| #define LONGDOUBLEPREC_STR DOUBLEPREC_STR | |
| #else /* More than probably needed on Intel FP */ | |
| #define LONGDOUBLEPREC_REPR 20 | |
| #define LONGDOUBLEPREC_STR 12 | |
| #endif | |
| /**begin repeat | |
| * #kind = str, repr# | |
| * #KIND = STR, REPR# | |
| */ | |
| /**begin repeat1 | |
| * #name = cfloat, cdouble, clongdouble# | |
| * #NAME = FLOAT, DOUBLE, LONGDOUBLE# | |
| * #type = npy_cfloat, npy_cdouble, npy_clongdouble# | |
| * #suff = f, d, l# | |
| */ | |
| #define _FMT1 "%%.%i" NPY_@NAME@_FMT | |
| #define _FMT2 "%%+.%i" NPY_@NAME@_FMT | |
| static PyObject* | |
| legacy_@name@_format@kind@(@type@ val) | |
| { | |
| /* XXX: Find a correct size here for format string */ | |
| char format[64], buf[100], *res; | |
| /* | |
| * Ideally, we should handle this nan/inf stuff in NumpyOS_ascii_format* | |
| */ | |
| if (val.real == 0.0 && npy_signbit(val.real) == 0) { | |
| PyOS_snprintf(format, sizeof(format), _FMT1, @NAME@PREC_@KIND@); | |
| res = NumPyOS_ascii_format@suff@(buf, sizeof(buf) - 1, format, val.imag, 0); | |
| if (res == NULL) { | |
| PyErr_SetString(PyExc_RuntimeError, "Error while formatting"); | |
| return NULL; | |
| } | |
| if (!npy_isfinite(val.imag)) { | |
| strncat(buf, "*", 1); | |
| } | |
| strncat(buf, "j", 1); | |
| } | |
| else { | |
| char re[64], im[64]; | |
| if (npy_isfinite(val.real)) { | |
| PyOS_snprintf(format, sizeof(format), _FMT1, @NAME@PREC_@KIND@); | |
| res = NumPyOS_ascii_format@suff@(re, sizeof(re), format, | |
| val.real, 0); | |
| if (res == NULL) { | |
| PyErr_SetString(PyExc_RuntimeError, "Error while formatting"); | |
| return NULL; | |
| } | |
| } | |
| else { | |
| if (npy_isnan(val.real)) { | |
| strcpy(re, "nan"); | |
| } | |
| else if (val.real > 0){ | |
| strcpy(re, "inf"); | |
| } | |
| else { | |
| strcpy(re, "-inf"); | |
| } | |
| } | |
| if (npy_isfinite(val.imag)) { | |
| PyOS_snprintf(format, sizeof(format), _FMT2, @NAME@PREC_@KIND@); | |
| res = NumPyOS_ascii_format@suff@(im, sizeof(im), format, | |
| val.imag, 0); | |
| if (res == NULL) { | |
| PyErr_SetString(PyExc_RuntimeError, "Error while formatting"); | |
| return NULL; | |
| } | |
| } | |
| else { | |
| if (npy_isnan(val.imag)) { | |
| strcpy(im, "+nan"); | |
| } | |
| else if (val.imag > 0){ | |
| strcpy(im, "+inf"); | |
| } | |
| else { | |
| strcpy(im, "-inf"); | |
| } | |
| if (!npy_isfinite(val.imag)) { | |
| strncat(im, "*", 1); | |
| } | |
| } | |
| PyOS_snprintf(buf, sizeof(buf), "(%s%sj)", re, im); | |
| } | |
| return PyUString_FromString(buf); | |
| } | |
| #undef _FMT1 | |
| #undef _FMT2 | |
| /**end repeat1**/ | |
| /**begin repeat1 | |
| * #name = float, double, longdouble# | |
| * #Name = Float, Double, LongDouble# | |
| * #NAME = FLOAT, DOUBLE, LONGDOUBLE# | |
| * #suff = f, d, l# | |
| */ | |
| #define _FMT1 "%%.%i" NPY_@NAME@_FMT | |
| static PyObject * | |
| legacy_@name@_format@kind@(npy_@name@ val){ | |
| /* XXX: Find a correct size here for format string */ | |
| char format[64], buf[100], *res; | |
| size_t i, cnt; | |
| PyOS_snprintf(format, sizeof(format), _FMT1, @NAME@PREC_@KIND@); | |
| res = NumPyOS_ascii_format@suff@(buf, sizeof(buf), format, val, 0); | |
| if (res == NULL) { | |
| PyErr_SetString(PyExc_RuntimeError, "Error while formatting"); | |
| return NULL; | |
| } | |
| /* If nothing but digits after sign, append ".0" */ | |
| cnt = strlen(buf); | |
| for (i = (buf[0] == '-') ? 1 : 0; i < cnt; ++i) { | |
| if (!isdigit(Py_CHARMASK(buf[i]))) { | |
| break; | |
| } | |
| } | |
| if (i == cnt && sizeof(buf) >= cnt + 3) { | |
| strcpy(&buf[cnt],".0"); | |
| } | |
| return PyUString_FromString(buf); | |
| } | |
| #undef _FMT1 | |
| /**end repeat1**/ | |
| /**end repeat**/ | |
| /* | |
| * *** END LEGACY PRINTING MODE CODE *** | |
| */ | |
| /**begin repeat | |
| * #kind = str, repr# | |
| */ | |
| /**begin repeat1 | |
| * #name = float, double, longdouble# | |
| * #Name = Float, Double, LongDouble# | |
| * #NAME = FLOAT, DOUBLE, LONGDOUBLE# | |
| */ | |
| /* helper function choose scientific of fractional output, based on a cutoff */ | |
| static PyObject * | |
| @name@type_@kind@_either(npy_@name@ val, TrimMode trim_pos, TrimMode trim_sci, | |
| npy_bool sign) | |
| { | |
| npy_@name@ absval; | |
| if (npy_legacy_print_mode == 113) { | |
| return legacy_@name@_format@kind@(val); | |
| } | |
| absval = val < 0 ? -val : val; | |
| if (absval == 0 || (absval < 1.e16L && absval >= 1.e-4L) ) { | |
| return format_@name@(val, 0, -1, sign, trim_pos, -1, -1, -1); | |
| } | |
| return format_@name@(val, 1, -1, sign, trim_sci, -1, -1, -1); | |
| } | |
| static PyObject * | |
| @name@type_@kind@(PyObject *self) | |
| { | |
| return @name@type_@kind@_either(((Py@Name@ScalarObject *)self)->obval, | |
| TrimMode_LeaveOneZero, TrimMode_DptZeros, 0); | |
| } | |
| static PyObject * | |
| c@name@type_@kind@(PyObject *self) | |
| { | |
| PyObject *rstr, *istr, *ret; | |
| npy_c@name@ val = ((PyC@Name@ScalarObject *)self)->obval; | |
| TrimMode trim = TrimMode_DptZeros; | |
| if (npy_legacy_print_mode == 113) { | |
| return legacy_c@name@_format@kind@(val); | |
| } | |
| if (val.real == 0.0 && npy_signbit(val.real) == 0) { | |
| istr = @name@type_@kind@_either(val.imag, trim, trim, 0); | |
| if (istr == NULL) { | |
| return NULL; | |
| } | |
| PyUString_ConcatAndDel(&istr, PyUString_FromString("j")); | |
| return istr; | |
| } | |
| if (npy_isfinite(val.real)) { | |
| rstr = @name@type_@kind@_either(val.real, trim, trim, 0); | |
| if (rstr == NULL) { | |
| return NULL; | |
| } | |
| } | |
| else if (npy_isnan(val.real)) { | |
| rstr = PyUString_FromString("nan"); | |
| } | |
| else if (val.real > 0){ | |
| rstr = PyUString_FromString("inf"); | |
| } | |
| else { | |
| rstr = PyUString_FromString("-inf"); | |
| } | |
| if (npy_isfinite(val.imag)) { | |
| istr = @name@type_@kind@_either(val.imag, trim, trim, 1); | |
| if (istr == NULL) { | |
| return NULL; | |
| } | |
| } | |
| else if (npy_isnan(val.imag)) { | |
| istr = PyUString_FromString("+nan"); | |
| } | |
| else if (val.imag > 0){ | |
| istr = PyUString_FromString("+inf"); | |
| } | |
| else { | |
| istr = PyUString_FromString("-inf"); | |
| } | |
| ret = PyUString_FromString("("); | |
| PyUString_ConcatAndDel(&ret, rstr); | |
| PyUString_ConcatAndDel(&ret, istr); | |
| PyUString_ConcatAndDel(&ret, PyUString_FromString("j)")); | |
| return ret; | |
| } | |
| #undef PREC | |
| /**end repeat1**/ | |
| static PyObject * | |
| halftype_@kind@(PyObject *self) | |
| { | |
| npy_half val = ((PyHalfScalarObject *)self)->obval; | |
| float floatval = npy_half_to_float(val); | |
| float absval; | |
| if (npy_legacy_print_mode == 113) { | |
| return legacy_float_format@kind@(floatval); | |
| } | |
| absval = floatval < 0 ? -floatval : floatval; | |
| if (absval == 0 || (absval < 1.e16 && absval >= 1.e-4) ) { | |
| return format_half(val, 0, -1, 0, TrimMode_LeaveOneZero, -1, -1, -1); | |
| } | |
| return format_half(val, 1, -1, 0, TrimMode_DptZeros, -1, -1, -1); | |
| } | |
| /**end repeat**/ | |
| /**begin repeat | |
| * #char = ,c# | |
| * #CHAR = ,C# | |
| * #POST = ,.real# | |
| */ | |
| static PyObject * | |
| @char@longdoubletype_float(PyObject *self) | |
| { | |
| npy_longdouble val = PyArrayScalar_VAL(self, @CHAR@LongDouble)@POST@; | |
| return PyFloat_FromDouble((double) val); | |
| } | |
| static PyObject * | |
| @char@longdoubletype_long(PyObject *self) | |
| { | |
| npy_longdouble val = PyArrayScalar_VAL(self, @CHAR@LongDouble)@POST@; | |
| return npy_longdouble_to_PyLong(val); | |
| } | |
| #if !defined(NPY_PY3K) | |
| /**begin repeat1 | |
| * #name = int, hex, oct# | |
| */ | |
| static PyObject * | |
| @char@longdoubletype_@name@(PyObject *self) | |
| { | |
| PyObject *ret; | |
| PyObject *obj = @char@longdoubletype_long(self); | |
| if (obj == NULL) { | |
| return NULL; | |
| } | |
| ret = Py_TYPE(obj)->tp_as_number->nb_@name@(obj); | |
| Py_DECREF(obj); | |
| return ret; | |
| } | |
| /**end repeat1**/ | |
| #endif /* !defined(NPY_PY3K) */ | |
| /**end repeat**/ | |
| static PyNumberMethods gentype_as_number = { | |
| (binaryfunc)gentype_add, /*nb_add*/ | |
| (binaryfunc)gentype_subtract, /*nb_subtract*/ | |
| (binaryfunc)gentype_multiply, /*nb_multiply*/ | |
| #if defined(NPY_PY3K) | |
| #else | |
| (binaryfunc)gentype_divide, /*nb_divide*/ | |
| #endif | |
| (binaryfunc)gentype_remainder, /*nb_remainder*/ | |
| (binaryfunc)gentype_divmod, /*nb_divmod*/ | |
| (ternaryfunc)gentype_power, /*nb_power*/ | |
| (unaryfunc)gentype_negative, | |
| (unaryfunc)gentype_positive, /*nb_pos*/ | |
| (unaryfunc)gentype_absolute, /*(unaryfunc)gentype_abs,*/ | |
| (inquiry)gentype_nonzero_number, /*nb_nonzero*/ | |
| (unaryfunc)gentype_invert, /*nb_invert*/ | |
| (binaryfunc)gentype_lshift, /*nb_lshift*/ | |
| (binaryfunc)gentype_rshift, /*nb_rshift*/ | |
| (binaryfunc)gentype_and, /*nb_and*/ | |
| (binaryfunc)gentype_xor, /*nb_xor*/ | |
| (binaryfunc)gentype_or, /*nb_or*/ | |
| #if defined(NPY_PY3K) | |
| #else | |
| 0, /*nb_coerce*/ | |
| #endif | |
| (unaryfunc)gentype_int, /*nb_int*/ | |
| #if defined(NPY_PY3K) | |
| 0, /*nb_reserved*/ | |
| #else | |
| (unaryfunc)gentype_long, /*nb_long*/ | |
| #endif | |
| (unaryfunc)gentype_float, /*nb_float*/ | |
| #if defined(NPY_PY3K) | |
| #else | |
| (unaryfunc)gentype_oct, /*nb_oct*/ | |
| (unaryfunc)gentype_hex, /*nb_hex*/ | |
| #endif | |
| 0, /*inplace_add*/ | |
| 0, /*inplace_subtract*/ | |
| 0, /*inplace_multiply*/ | |
| #if defined(NPY_PY3K) | |
| #else | |
| 0, /*inplace_divide*/ | |
| #endif | |
| 0, /*inplace_remainder*/ | |
| 0, /*inplace_power*/ | |
| 0, /*inplace_lshift*/ | |
| 0, /*inplace_rshift*/ | |
| 0, /*inplace_and*/ | |
| 0, /*inplace_xor*/ | |
| 0, /*inplace_or*/ | |
| (binaryfunc)gentype_floor_divide, /*nb_floor_divide*/ | |
| (binaryfunc)gentype_true_divide, /*nb_true_divide*/ | |
| 0, /*nb_inplace_floor_divide*/ | |
| 0, /*nb_inplace_true_divide*/ | |
| (unaryfunc)NULL, /*nb_index*/ | |
| }; | |
| static PyObject * | |
| gentype_richcompare(PyObject *self, PyObject *other, int cmp_op) | |
| { | |
| PyObject *arr, *ret; | |
| /* | |
| * If the other object is None, False is always right. This avoids | |
| * the array None comparison, at least until deprecation it is fixed. | |
| * After that, this may be removed and numpy false would be returned. | |
| * | |
| * NOTE: np.equal(NaT, None) evaluates to TRUE! This is an | |
| * an inconsistency, which may has to be considered | |
| * when the deprecation is finished. | |
| */ | |
| if (other == Py_None) { | |
| if (cmp_op == Py_EQ) { | |
| Py_RETURN_FALSE; | |
| } | |
| if (cmp_op == Py_NE) { | |
| Py_RETURN_TRUE; | |
| } | |
| } | |
| arr = PyArray_FromScalar(self, NULL); | |
| if (arr == NULL) { | |
| return NULL; | |
| } | |
| /* | |
| * Call via PyObject_RichCompare to ensure that other.__eq__ | |
| * has a chance to run when necessary | |
| */ | |
| ret = PyObject_RichCompare(arr, other, cmp_op); | |
| Py_DECREF(arr); | |
| return ret; | |
| } | |
| static PyObject * | |
| gentype_ndim_get(PyObject *NPY_UNUSED(self)) | |
| { | |
| return PyInt_FromLong(0); | |
| } | |
| static PyObject * | |
| gentype_flags_get(PyObject *NPY_UNUSED(self)) | |
| { | |
| return PyArray_NewFlagsObject(NULL); | |
| } | |
| static PyObject * | |
| voidtype_flags_get(PyVoidScalarObject *self) | |
| { | |
| PyObject *flagobj; | |
| flagobj = PyArrayFlags_Type.tp_alloc(&PyArrayFlags_Type, 0); | |
| if (flagobj == NULL) { | |
| return NULL; | |
| } | |
| ((PyArrayFlagsObject *)flagobj)->arr = NULL; | |
| ((PyArrayFlagsObject *)flagobj)->flags = self->flags; | |
| return flagobj; | |
| } | |
| static PyObject * | |
| voidtype_dtypedescr_get(PyVoidScalarObject *self) | |
| { | |
| Py_INCREF(self->descr); | |
| return (PyObject *)self->descr; | |
| } | |
| static PyObject * | |
| inttype_numerator_get(PyObject *self) | |
| { | |
| Py_INCREF(self); | |
| return self; | |
| } | |
| static PyObject * | |
| inttype_denominator_get(PyObject *self) | |
| { | |
| return PyInt_FromLong(1); | |
| } | |
| static PyObject * | |
| gentype_data_get(PyObject *self) | |
| { | |
| #if defined(NPY_PY3K) | |
| return PyMemoryView_FromObject(self); | |
| #else | |
| return PyBuffer_FromObject(self, 0, Py_END_OF_BUFFER); | |
| #endif | |
| } | |
| static PyObject * | |
| gentype_itemsize_get(PyObject *self) | |
| { | |
| PyArray_Descr *typecode; | |
| PyObject *ret; | |
| int elsize; | |
| typecode = PyArray_DescrFromScalar(self); | |
| elsize = typecode->elsize; | |
| #ifndef Py_UNICODE_WIDE | |
| if (typecode->type_num == NPY_UNICODE) { | |
| elsize >>= 1; | |
| } | |
| #endif | |
| ret = PyInt_FromLong((long) elsize); | |
| Py_DECREF(typecode); | |
| return ret; | |
| } | |
| static PyObject * | |
| gentype_size_get(PyObject *NPY_UNUSED(self)) | |
| { | |
| return PyInt_FromLong(1); | |
| } | |
| static PyObject * | |
| gentype_sizeof(PyObject *self) | |
| { | |
| Py_ssize_t nbytes; | |
| PyObject * isz = gentype_itemsize_get(self); | |
| if (isz == NULL) { | |
| return NULL; | |
| } | |
| nbytes = PyLong_AsLong(isz) + Py_TYPE(self)->tp_basicsize + | |
| Py_SIZE(self) * Py_TYPE(self)->tp_itemsize; | |
| Py_DECREF(isz); | |
| return PyLong_FromSsize_t(nbytes); | |
| } | |
| #if PY_VERSION_HEX >= 0x03000000 | |
| NPY_NO_EXPORT void | |
| gentype_struct_free(PyObject *ptr) | |
| { | |
| PyArrayInterface *arrif; | |
| PyObject *context; | |
| arrif = (PyArrayInterface*)PyCapsule_GetPointer(ptr, NULL); | |
| context = (PyObject *)PyCapsule_GetContext(ptr); | |
| Py_DECREF(context); | |
| Py_XDECREF(arrif->descr); | |
| PyArray_free(arrif->shape); | |
| PyArray_free(arrif); | |
| } | |
| #else | |
| NPY_NO_EXPORT void | |
| gentype_struct_free(void *ptr, void *arg) | |
| { | |
| PyArrayInterface *arrif = (PyArrayInterface *)ptr; | |
| Py_DECREF((PyObject *)arg); | |
| Py_XDECREF(arrif->descr); | |
| PyArray_free(arrif->shape); | |
| PyArray_free(arrif); | |
| } | |
| #endif | |
| static PyObject * | |
| gentype_struct_get(PyObject *self) | |
| { | |
| PyArrayObject *arr; | |
| PyArrayInterface *inter; | |
| PyObject *ret; | |
| arr = (PyArrayObject *)PyArray_FromScalar(self, NULL); | |
| inter = (PyArrayInterface *)PyArray_malloc(sizeof(PyArrayInterface)); | |
| inter->two = 2; | |
| inter->nd = 0; | |
| inter->flags = PyArray_FLAGS(arr); | |
| inter->flags &= ~(NPY_ARRAY_UPDATEIFCOPY | NPY_ARRAY_WRITEBACKIFCOPY | | |
| NPY_ARRAY_OWNDATA); | |
| inter->flags |= NPY_ARRAY_NOTSWAPPED; | |
| inter->typekind = PyArray_DESCR(arr)->kind; | |
| inter->itemsize = PyArray_DESCR(arr)->elsize; | |
| inter->strides = NULL; | |
| inter->shape = NULL; | |
| inter->data = PyArray_DATA(arr); | |
| inter->descr = NULL; | |
| ret = NpyCapsule_FromVoidPtrAndDesc(inter, arr, gentype_struct_free); | |
| return ret; | |
| } | |
| static PyObject * | |
| gentype_priority_get(PyObject *NPY_UNUSED(self)) | |
| { | |
| return PyFloat_FromDouble(NPY_SCALAR_PRIORITY); | |
| } | |
| static PyObject * | |
| gentype_shape_get(PyObject *NPY_UNUSED(self)) | |
| { | |
| return PyTuple_New(0); | |
| } | |
| static PyObject * | |
| gentype_interface_get(PyObject *self) | |
| { | |
| PyArrayObject *arr; | |
| PyObject *inter; | |
| arr = (PyArrayObject *)PyArray_FromScalar(self, NULL); | |
| if (arr == NULL) { | |
| return NULL; | |
| } | |
| inter = PyObject_GetAttrString((PyObject *)arr, "__array_interface__"); | |
| if (inter != NULL) { | |
| PyDict_SetItemString(inter, "__ref", (PyObject *)arr); | |
| } | |
| Py_DECREF(arr); | |
| return inter; | |
| } | |
| static PyObject * | |
| gentype_typedescr_get(PyObject *self) | |
| { | |
| return (PyObject *)PyArray_DescrFromScalar(self); | |
| } | |
| static PyObject * | |
| gentype_base_get(PyObject *NPY_UNUSED(self)) | |
| { | |
| Py_RETURN_NONE; | |
| } | |
| static PyObject * | |
| voidtype_base_get(PyVoidScalarObject *self) | |
| { | |
| if (self->base == NULL) { | |
| Py_RETURN_NONE; | |
| } | |
| else { | |
| Py_INCREF(self->base); | |
| return self->base; | |
| } | |
| } | |
| static PyArray_Descr * | |
| _realdescr_fromcomplexscalar(PyObject *self, int *typenum) | |
| { | |
| if (PyArray_IsScalar(self, CDouble)) { | |
| *typenum = NPY_CDOUBLE; | |
| return PyArray_DescrFromType(NPY_DOUBLE); | |
| } | |
| if (PyArray_IsScalar(self, CFloat)) { | |
| *typenum = NPY_CFLOAT; | |
| return PyArray_DescrFromType(NPY_FLOAT); | |
| } | |
| if (PyArray_IsScalar(self, CLongDouble)) { | |
| *typenum = NPY_CLONGDOUBLE; | |
| return PyArray_DescrFromType(NPY_LONGDOUBLE); | |
| } | |
| return NULL; | |
| } | |
| static PyObject * | |
| gentype_real_get(PyObject *self) | |
| { | |
| PyArray_Descr *typecode; | |
| PyObject *ret; | |
| int typenum; | |
| if (PyArray_IsScalar(self, ComplexFloating)) { | |
| void *ptr; | |
| typecode = _realdescr_fromcomplexscalar(self, &typenum); | |
| ptr = scalar_value(self, NULL); | |
| ret = PyArray_Scalar(ptr, typecode, NULL); | |
| Py_DECREF(typecode); | |
| return ret; | |
| } | |
| else if (PyArray_IsScalar(self, Object)) { | |
| PyObject *obj = ((PyObjectScalarObject *)self)->obval; | |
| ret = PyObject_GetAttrString(obj, "real"); | |
| if (ret != NULL) { | |
| return ret; | |
| } | |
| PyErr_Clear(); | |
| } | |
| Py_INCREF(self); | |
| return (PyObject *)self; | |
| } | |
| static PyObject * | |
| gentype_imag_get(PyObject *self) | |
| { | |
| PyArray_Descr *typecode=NULL; | |
| PyObject *ret; | |
| int typenum; | |
| if (PyArray_IsScalar(self, ComplexFloating)) { | |
| char *ptr; | |
| typecode = _realdescr_fromcomplexscalar(self, &typenum); | |
| ptr = (char *)scalar_value(self, NULL); | |
| ret = PyArray_Scalar(ptr + typecode->elsize, typecode, NULL); | |
| } | |
| else if (PyArray_IsScalar(self, Object)) { | |
| PyObject *obj = ((PyObjectScalarObject *)self)->obval; | |
| PyArray_Descr *newtype; | |
| ret = PyObject_GetAttrString(obj, "imag"); | |
| if (ret == NULL) { | |
| PyErr_Clear(); | |
| obj = PyInt_FromLong(0); | |
| newtype = PyArray_DescrFromType(NPY_OBJECT); | |
| ret = PyArray_Scalar((char *)&obj, newtype, NULL); | |
| Py_DECREF(newtype); | |
| Py_DECREF(obj); | |
| } | |
| } | |
| else { | |
| char *temp; | |
| int elsize; | |
| typecode = PyArray_DescrFromScalar(self); | |
| elsize = typecode->elsize; | |
| temp = npy_alloc_cache_zero(elsize); | |
| ret = PyArray_Scalar(temp, typecode, NULL); | |
| npy_free_cache(temp, elsize); | |
| } | |
| Py_XDECREF(typecode); | |
| return ret; | |
| } | |
| static PyObject * | |
| gentype_flat_get(PyObject *self) | |
| { | |
| PyObject *ret, *arr; | |
| arr = PyArray_FromScalar(self, NULL); | |
| if (arr == NULL) { | |
| return NULL; | |
| } | |
| ret = PyArray_IterNew(arr); | |
| Py_DECREF(arr); | |
| return ret; | |
| } | |
| static PyObject * | |
| gentype_transpose_get(PyObject *self) | |
| { | |
| Py_INCREF(self); | |
| return self; | |
| } | |
| static PyGetSetDef gentype_getsets[] = { | |
| {"ndim", | |
| (getter)gentype_ndim_get, | |
| (setter) 0, | |
| "number of array dimensions", | |
| NULL}, | |
| {"flags", | |
| (getter)gentype_flags_get, | |
| (setter)0, | |
| "integer value of flags", | |
| NULL}, | |
| {"shape", | |
| (getter)gentype_shape_get, | |
| (setter)0, | |
| "tuple of array dimensions", | |
| NULL}, | |
| {"strides", | |
| (getter)gentype_shape_get, | |
| (setter) 0, | |
| "tuple of bytes steps in each dimension", | |
| NULL}, | |
| {"data", | |
| (getter)gentype_data_get, | |
| (setter) 0, | |
| "pointer to start of data", | |
| NULL}, | |
| {"itemsize", | |
| (getter)gentype_itemsize_get, | |
| (setter)0, | |
| "length of one element in bytes", | |
| NULL}, | |
| {"size", | |
| (getter)gentype_size_get, | |
| (setter)0, | |
| "number of elements in the gentype", | |
| NULL}, | |
| {"nbytes", | |
| (getter)gentype_itemsize_get, | |
| (setter)0, | |
| "length of item in bytes", | |
| NULL}, | |
| {"base", | |
| (getter)gentype_base_get, | |
| (setter)0, | |
| "base object", | |
| NULL}, | |
| {"dtype", | |
| (getter)gentype_typedescr_get, | |
| NULL, | |
| "get array data-descriptor", | |
| NULL}, | |
| {"real", | |
| (getter)gentype_real_get, | |
| (setter)0, | |
| "real part of scalar", | |
| NULL}, | |
| {"imag", | |
| (getter)gentype_imag_get, | |
| (setter)0, | |
| "imaginary part of scalar", | |
| NULL}, | |
| {"flat", | |
| (getter)gentype_flat_get, | |
| (setter)0, | |
| "a 1-d view of scalar", | |
| NULL}, | |
| {"T", | |
| (getter)gentype_transpose_get, | |
| (setter)0, | |
| "transpose", | |
| NULL}, | |
| {"__array_interface__", | |
| (getter)gentype_interface_get, | |
| NULL, | |
| "Array protocol: Python side", | |
| NULL}, | |
| {"__array_struct__", | |
| (getter)gentype_struct_get, | |
| NULL, | |
| "Array protocol: struct", | |
| NULL}, | |
| {"__array_priority__", | |
| (getter)gentype_priority_get, | |
| NULL, | |
| "Array priority.", | |
| NULL}, | |
| {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ | |
| }; | |
| /* 0-dim array from scalar object */ | |
| static char doc_getarray[] = "sc.__array__(dtype) return 0-dim array from " | |
| "scalar with specified dtype"; | |
| static PyObject * | |
| gentype_getarray(PyObject *scalar, PyObject *args) | |
| { | |
| PyArray_Descr *outcode=NULL; | |
| PyObject *ret; | |
| if (!PyArg_ParseTuple(args, "|O&:__array__", &PyArray_DescrConverter, | |
| &outcode)) { | |
| Py_XDECREF(outcode); | |
| return NULL; | |
| } | |
| ret = PyArray_FromScalar(scalar, outcode); | |
| return ret; | |
| } | |
| static char doc_sc_wraparray[] = "sc.__array_wrap__(obj) return scalar from array"; | |
| static PyObject * | |
| gentype_wraparray(PyObject *NPY_UNUSED(scalar), PyObject *args) | |
| { | |
| PyObject *obj; | |
| PyArrayObject *arr; | |
| if (PyTuple_Size(args) < 1) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "only accepts 1 argument."); | |
| return NULL; | |
| } | |
| obj = PyTuple_GET_ITEM(args, 0); | |
| if (!PyArray_Check(obj)) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "can only be called with ndarray object"); | |
| return NULL; | |
| } | |
| arr = (PyArrayObject *)obj; | |
| return PyArray_Scalar(PyArray_DATA(arr), | |
| PyArray_DESCR(arr), (PyObject *)arr); | |
| } | |
| /* | |
| * These gentype_* functions do not take keyword arguments. | |
| * The proper flag is METH_VARARGS. | |
| */ | |
| /**begin repeat | |
| * | |
| * #name = tolist, item, __deepcopy__, __copy__, | |
| * swapaxes, conj, conjugate, nonzero, | |
| * fill, transpose, newbyteorder# | |
| */ | |
| static PyObject * | |
| gentype_@name@(PyObject *self, PyObject *args) | |
| { | |
| return gentype_generic_method(self, args, NULL, "@name@"); | |
| } | |
| /**end repeat**/ | |
| static PyObject * | |
| gentype_itemset(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args)) | |
| { | |
| PyErr_SetString(PyExc_ValueError, "array-scalars are immutable"); | |
| return NULL; | |
| } | |
| static Py_ssize_t | |
| gentype_getreadbuf(PyObject *, Py_ssize_t, void **); | |
| static PyObject * | |
| gentype_byteswap(PyObject *self, PyObject *args, PyObject *kwds) | |
| { | |
| npy_bool inplace = NPY_FALSE; | |
| static char *kwlist[] = {"inplace", NULL}; | |
| if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&:byteswap", kwlist, | |
| PyArray_BoolConverter, &inplace)) { | |
| return NULL; | |
| } | |
| if (inplace) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "cannot byteswap a scalar in-place"); | |
| return NULL; | |
| } | |
| else { | |
| /* get the data, copyswap it and pass it to a new Array scalar */ | |
| char *data; | |
| PyArray_Descr *descr; | |
| PyObject *new; | |
| char *newmem; | |
| gentype_getreadbuf(self, 0, (void **)&data); | |
| descr = PyArray_DescrFromScalar(self); | |
| newmem = PyObject_Malloc(descr->elsize); | |
| if (newmem == NULL) { | |
| Py_DECREF(descr); | |
| return PyErr_NoMemory(); | |
| } | |
| else { | |
| descr->f->copyswap(newmem, data, 1, NULL); | |
| } | |
| new = PyArray_Scalar(newmem, descr, NULL); | |
| PyObject_Free(newmem); | |
| Py_DECREF(descr); | |
| return new; | |
| } | |
| } | |
| /* | |
| * These gentype_* functions take keyword arguments. | |
| * The proper flag is METH_VARARGS | METH_KEYWORDS. | |
| */ | |
| /**begin repeat | |
| * | |
| * #name = take, getfield, put, repeat, tofile, mean, trace, diagonal, clip, | |
| * std, var, sum, cumsum, prod, cumprod, compress, sort, argsort, | |
| * round, argmax, argmin, max, min, ptp, any, all, astype, resize, | |
| * reshape, choose, tostring, tobytes, copy, searchsorted, view, | |
| * flatten, ravel, squeeze# | |
| */ | |
| static PyObject * | |
| gentype_@name@(PyObject *self, PyObject *args, PyObject *kwds) | |
| { | |
| return gentype_generic_method(self, args, kwds, "@name@"); | |
| } | |
| /**end repeat**/ | |
| static PyObject * | |
| voidtype_getfield(PyVoidScalarObject *self, PyObject *args, PyObject *kwds) | |
| { | |
| /* Use ndarray's getfield to obtain the field safely */ | |
| return gentype_generic_method((PyObject *)self, args, kwds, "getfield"); | |
| } | |
| static PyObject * | |
| gentype_setfield(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args), | |
| PyObject *NPY_UNUSED(kwds)) | |
| { | |
| PyErr_SetString(PyExc_TypeError, | |
| "Can't set fields in a non-void array scalar."); | |
| return NULL; | |
| } | |
| static PyObject * | |
| voidtype_setfield(PyVoidScalarObject *self, PyObject *args, PyObject *kwds) | |
| { | |
| /* | |
| * We would like to use ndarray's setfield because it performs safety | |
| * checks on the field datatypes and because it broadcasts properly. | |
| * However, as a special case, void-scalar assignment broadcasts | |
| * differently from ndarrays when assigning to an object field: Assignment | |
| * to an ndarray object field broadcasts, but assignment to a void-scalar | |
| * object-field should not, in order to allow nested ndarrays. | |
| * These lines should then behave identically: | |
| * | |
| * b = np.zeros(1, dtype=[('x', 'O')]) | |
| * b[0]['x'] = arange(3) # uses voidtype_setfield | |
| * b['x'][0] = arange(3) # uses ndarray setitem | |
| * | |
| * Ndarray's setfield would try to broadcast the lhs. Instead we use | |
| * ndarray getfield to get the field safely, then setitem with an empty | |
| * tuple to set the value without broadcast. Note we also want subarrays to | |
| * be set properly, ie | |
| * | |
| * a = np.zeros(1, dtype=[('x', 'i', 5)]) | |
| * a[0]['x'] = 1 | |
| * | |
| * sets all values to 1. "getfield + setitem with empty tuple" takes | |
| * care of both object arrays and subarrays. | |
| */ | |
| PyObject *getfield_args, *value, *arr, *meth, *arr_field, *emptytuple; | |
| value = PyTuple_GetItem(args, 0); | |
| if (value == NULL) { | |
| return NULL; | |
| } | |
| getfield_args = PyTuple_GetSlice(args, 1, 3); | |
| if (getfield_args == NULL) { | |
| return NULL; | |
| } | |
| /* 1. Convert to 0-d array and use getfield */ | |
| arr = PyArray_FromScalar((PyObject*)self, NULL); | |
| if (arr == NULL) { | |
| Py_DECREF(getfield_args); | |
| return NULL; | |
| } | |
| meth = PyObject_GetAttrString(arr, "getfield"); | |
| if (meth == NULL) { | |
| Py_DECREF(getfield_args); | |
| Py_DECREF(arr); | |
| return NULL; | |
| } | |
| if (kwds == NULL) { | |
| arr_field = PyObject_CallObject(meth, getfield_args); | |
| } | |
| else { | |
| arr_field = PyObject_Call(meth, getfield_args, kwds); | |
| } | |
| Py_DECREF(getfield_args); | |
| Py_DECREF(meth); | |
| Py_DECREF(arr); | |
| if(arr_field == NULL){ | |
| return NULL; | |
| } | |
| /* 2. Assign the value using setitem with empty tuple. */ | |
| emptytuple = PyTuple_New(0); | |
| if (PyObject_SetItem(arr_field, emptytuple, value) < 0) { | |
| Py_DECREF(arr_field); | |
| Py_DECREF(emptytuple); | |
| return NULL; | |
| } | |
| Py_DECREF(emptytuple); | |
| Py_DECREF(arr_field); | |
| Py_RETURN_NONE; | |
| } | |
| static PyObject * | |
| gentype_reduce(PyObject *self, PyObject *NPY_UNUSED(args)) | |
| { | |
| PyObject *ret = NULL, *obj = NULL, *mod = NULL; | |
| #if defined(NPY_PY3K) | |
| Py_buffer view; | |
| #endif | |
| const char *buffer; | |
| Py_ssize_t buflen; | |
| /* Return a tuple of (callable object, arguments) */ | |
| ret = PyTuple_New(2); | |
| if (ret == NULL) { | |
| return NULL; | |
| } | |
| #if defined(NPY_PY3K) | |
| if (PyArray_IsScalar(self, Unicode)) { | |
| /* Unicode on Python 3 does not expose the buffer interface */ | |
| buffer = PyUnicode_AS_DATA(self); | |
| buflen = PyUnicode_GET_DATA_SIZE(self); | |
| } | |
| else if (PyObject_GetBuffer(self, &view, PyBUF_SIMPLE) >= 0) { | |
| buffer = view.buf; | |
| buflen = view.len; | |
| /* | |
| * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and | |
| * PyObject_AsReadBuffer that this code replaces release the buffer. It is | |
| * up to the object that supplies the buffer to guarantee that the buffer | |
| * sticks around after the release. | |
| */ | |
| PyBuffer_Release(&view); | |
| } | |
| else { | |
| Py_DECREF(ret); | |
| return NULL; | |
| } | |
| #else | |
| if (PyObject_AsReadBuffer(self, (const void **)&buffer, &buflen)<0) { | |
| Py_DECREF(ret); | |
| return NULL; | |
| } | |
| #endif | |
| mod = PyImport_ImportModule("numpy.core._multiarray_umath"); | |
| if (mod == NULL) { | |
| return NULL; | |
| } | |
| obj = PyObject_GetAttrString(mod, "scalar"); | |
| Py_DECREF(mod); | |
| if (obj == NULL) { | |
| return NULL; | |
| } | |
| PyTuple_SET_ITEM(ret, 0, obj); | |
| obj = PyObject_GetAttrString((PyObject *)self, "dtype"); | |
| if (PyArray_IsScalar(self, Object)) { | |
| mod = ((PyObjectScalarObject *)self)->obval; | |
| PyTuple_SET_ITEM(ret, 1, Py_BuildValue("NO", obj, mod)); | |
| } | |
| else { | |
| #ifndef Py_UNICODE_WIDE | |
| /* | |
| * We need to expand the buffer so that we always write | |
| * UCS4 to disk for pickle of unicode scalars. | |
| * | |
| * This could be in a unicode_reduce function, but | |
| * that would require re-factoring. | |
| */ | |
| int alloc = 0; | |
| char *tmp; | |
| int newlen; | |
| if (PyArray_IsScalar(self, Unicode)) { | |
| tmp = PyArray_malloc(buflen*2); | |
| if (tmp == NULL) { | |
| Py_DECREF(ret); | |
| return PyErr_NoMemory(); | |
| } | |
| alloc = 1; | |
| newlen = PyUCS2Buffer_AsUCS4((Py_UNICODE *)buffer, | |
| (npy_ucs4 *)tmp, | |
| buflen / 2, buflen / 2); | |
| buflen = newlen*4; | |
| buffer = tmp; | |
| } | |
| #endif | |
| mod = PyBytes_FromStringAndSize(buffer, buflen); | |
| if (mod == NULL) { | |
| Py_DECREF(ret); | |
| #ifndef Py_UNICODE_WIDE | |
| ret = NULL; | |
| goto fail; | |
| #else | |
| return NULL; | |
| #endif | |
| } | |
| PyTuple_SET_ITEM(ret, 1, | |
| Py_BuildValue("NN", obj, mod)); | |
| #ifndef Py_UNICODE_WIDE | |
| fail: | |
| if (alloc) PyArray_free((char *)buffer); | |
| #endif | |
| } | |
| return ret; | |
| } | |
| /* ignores everything */ | |
| static PyObject * | |
| gentype_setstate(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args)) | |
| { | |
| Py_RETURN_NONE; | |
| } | |
| static PyObject * | |
| gentype_dump(PyObject *self, PyObject *args) | |
| { | |
| PyObject *file = NULL; | |
| int ret; | |
| if (!PyArg_ParseTuple(args, "O:dump", &file)) { | |
| return NULL; | |
| } | |
| ret = PyArray_Dump(self, file, 2); | |
| if (ret < 0) { | |
| return NULL; | |
| } | |
| Py_RETURN_NONE; | |
| } | |
| static PyObject * | |
| gentype_dumps(PyObject *self, PyObject *args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return NULL; | |
| } | |
| return PyArray_Dumps(self, 2); | |
| } | |
| /* setting flags cannot be done for scalars */ | |
| static PyObject * | |
| gentype_setflags(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args), | |
| PyObject *NPY_UNUSED(kwds)) | |
| { | |
| Py_RETURN_NONE; | |
| } | |
| /* | |
| * casting complex numbers (that don't inherit from Python complex) | |
| * to Python complex | |
| */ | |
| /**begin repeat | |
| * #name = cfloat, clongdouble# | |
| * #Name = CFloat, CLongDouble# | |
| */ | |
| static PyObject * | |
| @name@_complex(PyObject *self, PyObject *NPY_UNUSED(args), | |
| PyObject *NPY_UNUSED(kwds)) | |
| { | |
| return PyComplex_FromDoubles(PyArrayScalar_VAL(self, @Name@).real, | |
| PyArrayScalar_VAL(self, @Name@).imag); | |
| } | |
| /**end repeat**/ | |
| /* | |
| * need to fill in doc-strings for these methods on import -- copy from | |
| * array docstrings | |
| */ | |
| static PyMethodDef gentype_methods[] = { | |
| {"tolist", | |
| (PyCFunction)gentype_tolist, | |
| METH_VARARGS, NULL}, | |
| {"item", | |
| (PyCFunction)gentype_item, | |
| METH_VARARGS, NULL}, | |
| {"itemset", | |
| (PyCFunction)gentype_itemset, | |
| METH_VARARGS, NULL}, | |
| {"tobytes", | |
| (PyCFunction)gentype_tobytes, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"tofile", | |
| (PyCFunction)gentype_tofile, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"tostring", | |
| (PyCFunction)gentype_tostring, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"byteswap", | |
| (PyCFunction)gentype_byteswap, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"astype", | |
| (PyCFunction)gentype_astype, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"getfield", | |
| (PyCFunction)gentype_getfield, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"setfield", | |
| (PyCFunction)gentype_setfield, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"copy", | |
| (PyCFunction)gentype_copy, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"resize", | |
| (PyCFunction)gentype_resize, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"__array__", | |
| (PyCFunction)gentype_getarray, | |
| METH_VARARGS, doc_getarray}, | |
| {"__array_wrap__", | |
| (PyCFunction)gentype_wraparray, | |
| METH_VARARGS, doc_sc_wraparray}, | |
| /* for the sys module */ | |
| {"__sizeof__", | |
| (PyCFunction)gentype_sizeof, | |
| METH_NOARGS, NULL}, | |
| /* for the copy module */ | |
| {"__copy__", | |
| (PyCFunction)gentype___copy__, | |
| METH_VARARGS, NULL}, | |
| {"__deepcopy__", | |
| (PyCFunction)gentype___deepcopy__, | |
| METH_VARARGS, NULL}, | |
| {"__reduce__", | |
| (PyCFunction) gentype_reduce, | |
| METH_VARARGS, NULL}, | |
| /* For consistency does nothing */ | |
| {"__setstate__", | |
| (PyCFunction) gentype_setstate, | |
| METH_VARARGS, NULL}, | |
| {"dumps", | |
| (PyCFunction) gentype_dumps, | |
| METH_VARARGS, NULL}, | |
| {"dump", | |
| (PyCFunction) gentype_dump, | |
| METH_VARARGS, NULL}, | |
| /* Methods for array */ | |
| {"fill", | |
| (PyCFunction)gentype_fill, | |
| METH_VARARGS, NULL}, | |
| {"transpose", | |
| (PyCFunction)gentype_transpose, | |
| METH_VARARGS, NULL}, | |
| {"take", | |
| (PyCFunction)gentype_take, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"put", | |
| (PyCFunction)gentype_put, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"repeat", | |
| (PyCFunction)gentype_repeat, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"choose", | |
| (PyCFunction)gentype_choose, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"sort", | |
| (PyCFunction)gentype_sort, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"argsort", | |
| (PyCFunction)gentype_argsort, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"searchsorted", | |
| (PyCFunction)gentype_searchsorted, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"argmax", | |
| (PyCFunction)gentype_argmax, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"argmin", | |
| (PyCFunction)gentype_argmin, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"reshape", | |
| (PyCFunction)gentype_reshape, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"squeeze", | |
| (PyCFunction)gentype_squeeze, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"view", | |
| (PyCFunction)gentype_view, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"swapaxes", | |
| (PyCFunction)gentype_swapaxes, | |
| METH_VARARGS, NULL}, | |
| {"max", | |
| (PyCFunction)gentype_max, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"min", | |
| (PyCFunction)gentype_min, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"ptp", | |
| (PyCFunction)gentype_ptp, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"mean", | |
| (PyCFunction)gentype_mean, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"trace", | |
| (PyCFunction)gentype_trace, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"diagonal", | |
| (PyCFunction)gentype_diagonal, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"clip", | |
| (PyCFunction)gentype_clip, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"conj", | |
| (PyCFunction)gentype_conj, | |
| METH_VARARGS, NULL}, | |
| {"conjugate", | |
| (PyCFunction)gentype_conjugate, | |
| METH_VARARGS, NULL}, | |
| {"nonzero", | |
| (PyCFunction)gentype_nonzero, | |
| METH_VARARGS, NULL}, | |
| {"std", | |
| (PyCFunction)gentype_std, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"var", | |
| (PyCFunction)gentype_var, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"sum", | |
| (PyCFunction)gentype_sum, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"cumsum", | |
| (PyCFunction)gentype_cumsum, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"prod", | |
| (PyCFunction)gentype_prod, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"cumprod", | |
| (PyCFunction)gentype_cumprod, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"all", | |
| (PyCFunction)gentype_all, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"any", | |
| (PyCFunction)gentype_any, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"compress", | |
| (PyCFunction)gentype_compress, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"flatten", | |
| (PyCFunction)gentype_flatten, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"ravel", | |
| (PyCFunction)gentype_ravel, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"round", | |
| (PyCFunction)gentype_round, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| #if defined(NPY_PY3K) | |
| /* Hook for the round() builtin */ | |
| {"__round__", | |
| (PyCFunction)gentype_round, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| #endif | |
| /* For the format function */ | |
| {"__format__", | |
| gentype_format, | |
| METH_VARARGS, | |
| "NumPy array scalar formatter"}, | |
| {"setflags", | |
| (PyCFunction)gentype_setflags, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"newbyteorder", | |
| (PyCFunction)gentype_newbyteorder, | |
| METH_VARARGS, NULL}, | |
| {NULL, NULL, 0, NULL} /* sentinel */ | |
| }; | |
| static PyGetSetDef voidtype_getsets[] = { | |
| {"flags", | |
| (getter)voidtype_flags_get, | |
| (setter)0, | |
| "integer value of flags", | |
| NULL}, | |
| {"dtype", | |
| (getter)voidtype_dtypedescr_get, | |
| (setter)0, | |
| "dtype object", | |
| NULL}, | |
| {"base", | |
| (getter)voidtype_base_get, | |
| (setter)0, | |
| "base object", | |
| NULL}, | |
| {NULL, NULL, NULL, NULL, NULL} | |
| }; | |
| static PyMethodDef voidtype_methods[] = { | |
| {"getfield", | |
| (PyCFunction)voidtype_getfield, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {"setfield", | |
| (PyCFunction)voidtype_setfield, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {NULL, NULL, 0, NULL} | |
| }; | |
| static PyGetSetDef inttype_getsets[] = { | |
| {"numerator", | |
| (getter)inttype_numerator_get, | |
| (setter)0, | |
| "numerator of value (the value itself)", | |
| NULL}, | |
| {"denominator", | |
| (getter)inttype_denominator_get, | |
| (setter)0, | |
| "denominator of value (1)", | |
| NULL}, | |
| {NULL, NULL, NULL, NULL, NULL} | |
| }; | |
| /**begin repeat | |
| * #name = cfloat,clongdouble# | |
| */ | |
| static PyMethodDef @name@type_methods[] = { | |
| {"__complex__", | |
| (PyCFunction)@name@_complex, | |
| METH_VARARGS | METH_KEYWORDS, NULL}, | |
| {NULL, NULL, 0, NULL} | |
| }; | |
| /**end repeat**/ | |
| /************* As_mapping functions for void array scalar ************/ | |
| static Py_ssize_t | |
| voidtype_length(PyVoidScalarObject *self) | |
| { | |
| if (!PyDataType_HASFIELDS(self->descr)) { | |
| return 0; | |
| } | |
| else { | |
| /* return the number of fields */ | |
| return (Py_ssize_t) PyTuple_GET_SIZE(self->descr->names); | |
| } | |
| } | |
| static PyObject * | |
| voidtype_subscript(PyVoidScalarObject *self, PyObject *ind); | |
| static PyObject * | |
| voidtype_item(PyVoidScalarObject *self, Py_ssize_t n) | |
| { | |
| npy_intp m; | |
| PyObject *flist=NULL; | |
| if (!(PyDataType_HASFIELDS(self->descr))) { | |
| PyErr_SetString(PyExc_IndexError, | |
| "can't index void scalar without fields"); | |
| return NULL; | |
| } | |
| flist = self->descr->names; | |
| m = PyTuple_GET_SIZE(flist); | |
| if (n < 0) { | |
| n += m; | |
| } | |
| if (n < 0 || n >= m) { | |
| PyErr_Format(PyExc_IndexError, "invalid index (%d)", (int) n); | |
| return NULL; | |
| } | |
| return voidtype_subscript(self, PyTuple_GetItem(flist, n)); | |
| } | |
| /* get field by name or number */ | |
| static PyObject * | |
| voidtype_subscript(PyVoidScalarObject *self, PyObject *ind) | |
| { | |
| npy_intp n; | |
| PyObject *ret, *res; | |
| /* structured voids will accept an integer index */ | |
| if (PyDataType_HASFIELDS(self->descr)) { | |
| n = PyArray_PyIntAsIntp(ind); | |
| if (!error_converting(n)) { | |
| return voidtype_item(self, (Py_ssize_t)n); | |
| } | |
| PyErr_Clear(); | |
| } | |
| res = PyArray_FromScalar((PyObject*)self, NULL); | |
| /* ellipsis should return 0d array */ | |
| if(ind == Py_Ellipsis){ | |
| return res; | |
| } | |
| /* | |
| * other cases (field names, empty tuple) will return either | |
| * scalar or non-0d array. Compute this using ndarray subscript. | |
| */ | |
| ret = array_subscript((PyArrayObject *)res, ind); | |
| Py_DECREF(res); | |
| return PyArray_Return((PyArrayObject*)ret); | |
| } | |
| static int | |
| voidtype_ass_subscript(PyVoidScalarObject *self, PyObject *ind, PyObject *val); | |
| static int | |
| voidtype_ass_item(PyVoidScalarObject *self, Py_ssize_t n, PyObject *val) | |
| { | |
| npy_intp m; | |
| PyObject *flist=NULL; | |
| if (!(PyDataType_HASFIELDS(self->descr))) { | |
| PyErr_SetString(PyExc_IndexError, | |
| "can't index void scalar without fields"); | |
| return -1; | |
| } | |
| flist = self->descr->names; | |
| m = PyTuple_GET_SIZE(flist); | |
| if (n < 0) { | |
| n += m; | |
| } | |
| if (n < 0 || n >= m) { | |
| PyErr_Format(PyExc_IndexError, "invalid index (%d)", (int) n); | |
| return -1; | |
| } | |
| return voidtype_ass_subscript(self, PyTuple_GetItem(flist, n), val); | |
| } | |
| static int | |
| voidtype_ass_subscript(PyVoidScalarObject *self, PyObject *ind, PyObject *val) | |
| { | |
| npy_intp n; | |
| char *msg = "invalid index"; | |
| PyObject *args; | |
| if (!PyDataType_HASFIELDS(self->descr)) { | |
| PyErr_SetString(PyExc_IndexError, | |
| "can't index void scalar without fields"); | |
| return -1; | |
| } | |
| if (!val) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "cannot delete scalar field"); | |
| return -1; | |
| } | |
| if (PyBaseString_Check(ind)) { | |
| /* | |
| * Much like in voidtype_setfield, we cannot simply use ndarray's | |
| * __setitem__ since assignment to void scalars should not broadcast | |
| * the lhs. Instead we get a view through __getitem__ and then assign | |
| * the value using setitem with an empty tuple (which treats both | |
| * object arrays and subarrays properly). | |
| * | |
| * Also we do not want to use voidtype_setfield here, since we do | |
| * not need to do the (slow) view safety checks, since we already | |
| * know the dtype/offset are safe. | |
| */ | |
| PyObject *arr, *arr_field, *meth, *emptytuple; | |
| /* 1. Convert to 0-d array and use getitem */ | |
| arr = PyArray_FromScalar((PyObject*)self, NULL); | |
| if (arr == NULL) { | |
| return -1; | |
| } | |
| meth = PyObject_GetAttrString(arr, "__getitem__"); | |
| if (meth == NULL) { | |
| Py_DECREF(arr); | |
| return -1; | |
| } | |
| args = Py_BuildValue("(O)", ind); | |
| arr_field = PyObject_CallObject(meth, args); | |
| Py_DECREF(meth); | |
| Py_DECREF(arr); | |
| Py_DECREF(args); | |
| if(arr_field == NULL){ | |
| return -1; | |
| } | |
| /* 2. Assign the value using setitem with empty tuple. */ | |
| emptytuple = PyTuple_New(0); | |
| if (PyObject_SetItem(arr_field, emptytuple, val) < 0) { | |
| Py_DECREF(arr_field); | |
| Py_DECREF(emptytuple); | |
| return -1; | |
| } | |
| Py_DECREF(emptytuple); | |
| Py_DECREF(arr_field); | |
| return 0; | |
| } | |
| /* try to convert it to a number */ | |
| n = PyArray_PyIntAsIntp(ind); | |
| if (error_converting(n)) { | |
| goto fail; | |
| } | |
| return voidtype_ass_item(self, (Py_ssize_t)n, val); | |
| fail: | |
| PyErr_SetString(PyExc_IndexError, msg); | |
| return -1; | |
| } | |
| static PyMappingMethods voidtype_as_mapping = { | |
| (lenfunc)voidtype_length, /*mp_length*/ | |
| (binaryfunc)voidtype_subscript, /*mp_subscript*/ | |
| (objobjargproc)voidtype_ass_subscript, /*mp_ass_subscript*/ | |
| }; | |
| static PySequenceMethods voidtype_as_sequence = { | |
| (lenfunc)voidtype_length, /*sq_length*/ | |
| 0, /*sq_concat*/ | |
| 0, /*sq_repeat*/ | |
| (ssizeargfunc)voidtype_item, /*sq_item*/ | |
| 0, /*sq_slice*/ | |
| (ssizeobjargproc)voidtype_ass_item, /*sq_ass_item*/ | |
| 0, /* ssq_ass_slice */ | |
| 0, /* sq_contains */ | |
| 0, /* sq_inplace_concat */ | |
| 0, /* sq_inplace_repeat */ | |
| }; | |
| static Py_ssize_t | |
| gentype_getreadbuf(PyObject *self, Py_ssize_t segment, void **ptrptr) | |
| { | |
| int numbytes; | |
| PyArray_Descr *outcode; | |
| if (segment != 0) { | |
| PyErr_SetString(PyExc_SystemError, | |
| "Accessing non-existent array segment"); | |
| return -1; | |
| } | |
| outcode = PyArray_DescrFromScalar(self); | |
| numbytes = outcode->elsize; | |
| *ptrptr = (void *)scalar_value(self, outcode); | |
| #ifndef Py_UNICODE_WIDE | |
| if (outcode->type_num == NPY_UNICODE) { | |
| numbytes >>= 1; | |
| } | |
| #endif | |
| Py_DECREF(outcode); | |
| return numbytes; | |
| } | |
| #if !defined(NPY_PY3K) | |
| static Py_ssize_t | |
| gentype_getsegcount(PyObject *self, Py_ssize_t *lenp) | |
| { | |
| PyArray_Descr *outcode; | |
| outcode = PyArray_DescrFromScalar(self); | |
| if (lenp) { | |
| *lenp = outcode->elsize; | |
| #ifndef Py_UNICODE_WIDE | |
| if (outcode->type_num == NPY_UNICODE) { | |
| *lenp >>= 1; | |
| } | |
| #endif | |
| } | |
| Py_DECREF(outcode); | |
| return 1; | |
| } | |
| static Py_ssize_t | |
| gentype_getcharbuf(PyObject *self, Py_ssize_t segment, constchar **ptrptr) | |
| { | |
| if (PyArray_IsScalar(self, String) || | |
| PyArray_IsScalar(self, Unicode)) { | |
| return gentype_getreadbuf(self, segment, (void **)ptrptr); | |
| } | |
| else { | |
| PyErr_SetString(PyExc_TypeError, | |
| "Non-character array cannot be interpreted "\ | |
| "as character buffer."); | |
| return -1; | |
| } | |
| } | |
| #endif /* !defined(NPY_PY3K) */ | |
| static PyBufferProcs gentype_as_buffer = { | |
| #if !defined(NPY_PY3K) | |
| gentype_getreadbuf, /* bf_getreadbuffer*/ | |
| NULL, /* bf_getwritebuffer*/ | |
| gentype_getsegcount, /* bf_getsegcount*/ | |
| gentype_getcharbuf, /* bf_getcharbuffer*/ | |
| #endif | |
| gentype_getbuffer, /* bf_getbuffer */ | |
| NULL, /* bf_releasebuffer */ | |
| }; | |
| #if defined(NPY_PY3K) | |
| #define BASEFLAGS Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | |
| #define LEAFFLAGS Py_TPFLAGS_DEFAULT | |
| #else | |
| #define BASEFLAGS Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES | |
| #define LEAFFLAGS Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | |
| #endif | |
| NPY_NO_EXPORT PyTypeObject PyGenericArrType_Type = { | |
| #if defined(NPY_PY3K) | |
| PyVarObject_HEAD_INIT(NULL, 0) | |
| #else | |
| PyObject_HEAD_INIT(NULL) | |
| 0, /* ob_size */ | |
| #endif | |
| "numpy.generic", /* tp_name*/ | |
| sizeof(PyObject), /* tp_basicsize*/ | |
| 0, /* tp_itemsize */ | |
| /* methods */ | |
| 0, /* tp_dealloc */ | |
| 0, /* tp_print */ | |
| 0, /* tp_getattr */ | |
| 0, /* tp_setattr */ | |
| #if defined(NPY_PY3K) | |
| 0, /* tp_reserved */ | |
| #else | |
| 0, /* tp_compare */ | |
| #endif | |
| 0, /* tp_repr */ | |
| 0, /* tp_as_number */ | |
| 0, /* tp_as_sequence */ | |
| 0, /* tp_as_mapping */ | |
| 0, /* tp_hash */ | |
| 0, /* tp_call */ | |
| 0, /* tp_str */ | |
| 0, /* tp_getattro */ | |
| 0, /* tp_setattro */ | |
| 0, /* tp_as_buffer */ | |
| 0, /* tp_flags */ | |
| 0, /* tp_doc */ | |
| 0, /* tp_traverse */ | |
| 0, /* tp_clear */ | |
| 0, /* tp_richcompare */ | |
| 0, /* tp_weaklistoffset */ | |
| 0, /* tp_iter */ | |
| 0, /* tp_iternext */ | |
| 0, /* tp_methods */ | |
| 0, /* tp_members */ | |
| 0, /* tp_getset */ | |
| 0, /* tp_base */ | |
| 0, /* tp_dict */ | |
| 0, /* tp_descr_get */ | |
| 0, /* tp_descr_set */ | |
| 0, /* tp_dictoffset */ | |
| 0, /* tp_init */ | |
| 0, /* tp_alloc */ | |
| 0, /* tp_new */ | |
| 0, /* tp_free */ | |
| 0, /* tp_is_gc */ | |
| 0, /* tp_bases */ | |
| 0, /* tp_mro */ | |
| 0, /* tp_cache */ | |
| 0, /* tp_subclasses */ | |
| 0, /* tp_weaklist */ | |
| 0, /* tp_del */ | |
| 0, /* tp_version_tag */ | |
| }; | |
| static void | |
| void_dealloc(PyVoidScalarObject *v) | |
| { | |
| if (v->flags & NPY_ARRAY_OWNDATA) { | |
| npy_free_cache(v->obval, Py_SIZE(v)); | |
| } | |
| Py_XDECREF(v->descr); | |
| Py_XDECREF(v->base); | |
| Py_TYPE(v)->tp_free(v); | |
| } | |
| static void | |
| object_arrtype_dealloc(PyObject *v) | |
| { | |
| Py_XDECREF(((PyObjectScalarObject *)v)->obval); | |
| Py_TYPE(v)->tp_free(v); | |
| } | |
| /* | |
| * string and unicode inherit from Python Type first and so GET_ITEM | |
| * is different to get to the Python Type. | |
| * | |
| * ok is a work-around for a bug in complex_new that doesn't allocate | |
| * memory from the sub-types memory allocator. | |
| */ | |
| #define _WORK(num) \ | |
| if (type->tp_bases && (PyTuple_GET_SIZE(type->tp_bases)==2)) { \ | |
| PyTypeObject *sup; \ | |
| /* We are inheriting from a Python type as well so \ | |
| give it first dibs on conversion */ \ | |
| sup = (PyTypeObject *)PyTuple_GET_ITEM(type->tp_bases, num); \ | |
| /* Prevent recursion */ \ | |
| if (thisfunc != sup->tp_new) { \ | |
| robj = sup->tp_new(type, args, kwds); \ | |
| if (robj != NULL) goto finish; \ | |
| if (PyTuple_GET_SIZE(args)!=1) return NULL; \ | |
| PyErr_Clear(); \ | |
| } \ | |
| /* now do default conversion */ \ | |
| } | |
| #define _WORK1 _WORK(1) | |
| #define _WORKz _WORK(0) | |
| #define _WORK0 | |
| /**begin repeat | |
| * #name = byte, short, int, long, longlong, ubyte, ushort, uint, ulong, | |
| * ulonglong, half, float, double, longdouble, cfloat, cdouble, | |
| * clongdouble, string, unicode, object# | |
| * #Name = Byte, Short, Int, Long, LongLong, UByte, UShort, UInt, ULong, | |
| * ULongLong, Half, Float, Double, LongDouble, CFloat, CDouble, | |
| * CLongDouble, String, Unicode, Object# | |
| * #TYPE = BYTE, SHORT, INT, LONG, LONGLONG, UBYTE, USHORT, UINT, ULONG, | |
| * ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, | |
| * CLONGDOUBLE, STRING, UNICODE, OBJECT# | |
| * #work = 0,0,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,z,z,0# | |
| * #default = 0*17,1*2,2# | |
| */ | |
| #define _NPY_UNUSED2_1 | |
| #define _NPY_UNUSED2_z | |
| #define _NPY_UNUSED2_0 NPY_UNUSED | |
| #define _NPY_UNUSED1_0 | |
| #define _NPY_UNUSED1_1 | |
| #define _NPY_UNUSED1_2 NPY_UNUSED | |
| static PyObject * | |
| @name@_arrtype_new(PyTypeObject *_NPY_UNUSED1_@default@(type), PyObject *args, PyObject *_NPY_UNUSED2_@work@(kwds)) | |
| { | |
| PyObject *obj = NULL; | |
| PyObject *robj; | |
| PyArrayObject *arr; | |
| PyArray_Descr *typecode = NULL; | |
| #if (@work@ != 0) || (@default@ == 1) | |
| void *thisfunc = (void *)@name@_arrtype_new; | |
| #endif | |
| #if !(@default@ == 2) | |
| int itemsize; | |
| void *dest, *src; | |
| #endif | |
| /* | |
| * allow base-class (if any) to do conversion | |
| * If successful, this will jump to finish: | |
| */ | |
| _WORK@work@ | |
| /* TODO: include type name in error message, which is not @name@ */ | |
| if (!PyArg_ParseTuple(args, "|O", &obj)) { | |
| return NULL; | |
| } | |
| typecode = PyArray_DescrFromType(NPY_@TYPE@); | |
| if (typecode == NULL) { | |
| return NULL; | |
| } | |
| /* | |
| * typecode is new reference and stolen by | |
| * PyArray_FromAny but not PyArray_Scalar | |
| */ | |
| if (obj == NULL) { | |
| #if @default@ == 0 | |
| robj = PyArray_Scalar(NULL, typecode, NULL); | |
| if (robj == NULL) { | |
| Py_DECREF(typecode); | |
| return NULL; | |
| } | |
| memset(&((Py@Name@ScalarObject *)robj)->obval, 0, sizeof(npy_@name@)); | |
| #elif @default@ == 1 | |
| robj = PyArray_Scalar(NULL, typecode, NULL); | |
| #elif @default@ == 2 | |
| Py_INCREF(Py_None); | |
| robj = Py_None; | |
| #endif | |
| Py_DECREF(typecode); | |
| goto finish; | |
| } | |
| /* | |
| * It is expected at this point that robj is a PyArrayScalar | |
| * (even for Object Data Type) | |
| */ | |
| arr = (PyArrayObject *)PyArray_FromAny(obj, typecode, | |
| 0, 0, NPY_ARRAY_FORCECAST, NULL); | |
| if ((arr == NULL) || (PyArray_NDIM(arr) > 0)) { | |
| return (PyObject *)arr; | |
| } | |
| /* 0-d array */ | |
| robj = PyArray_ToScalar(PyArray_DATA(arr), arr); | |
| Py_DECREF(arr); | |
| finish: | |
| /* | |
| * In OBJECT case, robj is no longer a | |
| * PyArrayScalar at this point but the | |
| * remaining code assumes it is | |
| */ | |
| #if @default@ == 2 | |
| return robj; | |
| #else | |
| /* Normal return */ | |
| if ((robj == NULL) || (Py_TYPE(robj) == type)) { | |
| return robj; | |
| } | |
| /* | |
| * This return path occurs when the requested type is not created | |
| * but another scalar object is created instead (i.e. when | |
| * the base-class does the conversion in _WORK macro) | |
| */ | |
| /* Need to allocate new type and copy data-area over */ | |
| if (type->tp_itemsize) { | |
| itemsize = PyBytes_GET_SIZE(robj); | |
| } | |
| else { | |
| itemsize = 0; | |
| } | |
| obj = type->tp_alloc(type, itemsize); | |
| if (obj == NULL) { | |
| Py_DECREF(robj); | |
| return NULL; | |
| } | |
| /* typecode will be NULL */ | |
| typecode = PyArray_DescrFromType(NPY_@TYPE@); | |
| dest = scalar_value(obj, typecode); | |
| src = scalar_value(robj, typecode); | |
| Py_DECREF(typecode); | |
| #if @default@ == 0 | |
| *((npy_@name@ *)dest) = *((npy_@name@ *)src); | |
| #elif @default@ == 1 /* unicode and strings */ | |
| if (itemsize == 0) { /* unicode */ | |
| #if PY_VERSION_HEX >= 0x03030000 | |
| itemsize = PyUnicode_GetLength(robj) * PyUnicode_KIND(robj); | |
| #else | |
| itemsize = ((PyUnicodeObject *)robj)->length * sizeof(Py_UNICODE); | |
| #endif | |
| } | |
| memcpy(dest, src, itemsize); | |
| /* @default@ == 2 won't get here */ | |
| #endif | |
| Py_DECREF(robj); | |
| return obj; | |
| #endif | |
| } | |
| /**end repeat**/ | |
| #undef _WORK1 | |
| #undef _WORKz | |
| #undef _WORK0 | |
| #undef _WORK | |
| /**begin repeat | |
| * #name = datetime, timedelta# | |
| * #Name = Datetime, Timedelta# | |
| * #NAME = DATETIME, TIMEDELTA# | |
| * #is_datetime = 1, 0# | |
| */ | |
| static PyObject * | |
| @name@_arrtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| { | |
| PyObject *obj = NULL, *meta_obj = NULL; | |
| Py@Name@ScalarObject *ret; | |
| /* TODO: include type name in error message, which is not @name@ */ | |
| if (!PyArg_ParseTuple(args, "|OO", &obj, &meta_obj)) { | |
| return NULL; | |
| } | |
| /* Allocate the return scalar */ | |
| ret = (Py@Name@ScalarObject *)Py@Name@ArrType_Type.tp_alloc( | |
| &Py@Name@ArrType_Type, 0); | |
| if (ret == NULL) { | |
| return NULL; | |
| } | |
| /* Incorporate the metadata if its provided */ | |
| if (meta_obj != NULL) { | |
| /* Parse the provided metadata input */ | |
| if (convert_pyobject_to_datetime_metadata(meta_obj, &ret->obmeta) | |
| < 0) { | |
| Py_DECREF(ret); | |
| return NULL; | |
| } | |
| } | |
| else { | |
| /* | |
| * A unit of -1 signals that convert_pyobject_to_datetime | |
| * should populate. | |
| */ | |
| ret->obmeta.base = -1; | |
| } | |
| if (obj == NULL) { | |
| if (ret->obmeta.base == -1) { | |
| ret->obmeta.base = NPY_DATETIME_DEFAULTUNIT; | |
| ret->obmeta.num = 1; | |
| } | |
| /* Make datetime default to NaT, timedelta default to zero */ | |
| #if @is_datetime@ | |
| ret->obval = NPY_DATETIME_NAT; | |
| #else | |
| ret->obval = 0; | |
| #endif | |
| } | |
| else if (convert_pyobject_to_@name@(&ret->obmeta, obj, | |
| NPY_SAME_KIND_CASTING, &ret->obval) < 0) { | |
| Py_DECREF(ret); | |
| return NULL; | |
| } | |
| return (PyObject *)ret; | |
| } | |
| /**end repeat**/ | |
| /* bool->tp_new only returns Py_True or Py_False */ | |
| static PyObject * | |
| bool_arrtype_new(PyTypeObject *NPY_UNUSED(type), PyObject *args, PyObject *NPY_UNUSED(kwds)) | |
| { | |
| PyObject *obj = NULL; | |
| PyArrayObject *arr; | |
| if (!PyArg_ParseTuple(args, "|O:bool_", &obj)) { | |
| return NULL; | |
| } | |
| if (obj == NULL) { | |
| PyArrayScalar_RETURN_FALSE; | |
| } | |
| if (obj == Py_False) { | |
| PyArrayScalar_RETURN_FALSE; | |
| } | |
| if (obj == Py_True) { | |
| PyArrayScalar_RETURN_TRUE; | |
| } | |
| arr = (PyArrayObject *)PyArray_FROM_OTF(obj, | |
| NPY_BOOL, NPY_ARRAY_FORCECAST); | |
| if (arr && 0 == PyArray_NDIM(arr)) { | |
| npy_bool val = *((npy_bool *)PyArray_DATA(arr)); | |
| Py_DECREF(arr); | |
| PyArrayScalar_RETURN_BOOL_FROM_LONG(val); | |
| } | |
| return PyArray_Return((PyArrayObject *)arr); | |
| } | |
| static PyObject * | |
| bool_arrtype_and(PyObject *a, PyObject *b) | |
| { | |
| if (PyArray_IsScalar(a, Bool) && PyArray_IsScalar(b, Bool)) { | |
| PyArrayScalar_RETURN_BOOL_FROM_LONG | |
| ((a == PyArrayScalar_True) & (b == PyArrayScalar_True)); | |
| } | |
| return PyGenericArrType_Type.tp_as_number->nb_and(a, b); | |
| } | |
| static PyObject * | |
| bool_arrtype_or(PyObject *a, PyObject *b) | |
| { | |
| if (PyArray_IsScalar(a, Bool) && PyArray_IsScalar(b, Bool)) { | |
| PyArrayScalar_RETURN_BOOL_FROM_LONG | |
| ((a == PyArrayScalar_True)|(b == PyArrayScalar_True)); | |
| } | |
| return PyGenericArrType_Type.tp_as_number->nb_or(a, b); | |
| } | |
| static PyObject * | |
| bool_arrtype_xor(PyObject *a, PyObject *b) | |
| { | |
| if (PyArray_IsScalar(a, Bool) && PyArray_IsScalar(b, Bool)) { | |
| PyArrayScalar_RETURN_BOOL_FROM_LONG | |
| ((a == PyArrayScalar_True)^(b == PyArrayScalar_True)); | |
| } | |
| return PyGenericArrType_Type.tp_as_number->nb_xor(a, b); | |
| } | |
| static int | |
| bool_arrtype_nonzero(PyObject *a) | |
| { | |
| return a == PyArrayScalar_True; | |
| } | |
| /**begin repeat | |
| * #name = byte, short, int, long, ubyte, ushort, longlong, uint, | |
| * ulong, ulonglong# | |
| * #Name = Byte, Short, Int, Long, UByte, UShort, LongLong, UInt, | |
| * ULong, ULongLong# | |
| * #type = PyInt_FromLong*6, PyLong_FromLongLong*1, | |
| * PyLong_FromUnsignedLong*2, PyLong_FromUnsignedLongLong# | |
| */ | |
| static PyNumberMethods @name@_arrtype_as_number; | |
| static PyObject * | |
| @name@_index(PyObject *self) | |
| { | |
| return @type@(PyArrayScalar_VAL(self, @Name@)); | |
| } | |
| /**end repeat**/ | |
| /**begin repeat | |
| * #name = half, float, double, longdouble, | |
| * cfloat, cdouble, clongdouble# | |
| * #NAME = Half, Float, Double, LongDouble, | |
| * CFloat, CDouble, CLongDouble# | |
| */ | |
| static PyNumberMethods @name@_arrtype_as_number; | |
| /**end repeat**/ | |
| static PyObject * | |
| bool_index(PyObject *a) | |
| { | |
| if (DEPRECATE( | |
| "In future, it will be an error for 'np.bool_' scalars to be " | |
| "interpreted as an index") < 0) { | |
| return NULL; | |
| } | |
| else { | |
| return PyInt_FromLong(PyArrayScalar_VAL(a, Bool)); | |
| } | |
| } | |
| /* Arithmetic methods -- only so we can override &, |, ^. */ | |
| NPY_NO_EXPORT PyNumberMethods bool_arrtype_as_number = { | |
| 0, /* nb_add */ | |
| 0, /* nb_subtract */ | |
| 0, /* nb_multiply */ | |
| #if defined(NPY_PY3K) | |
| #else | |
| 0, /* nb_divide */ | |
| #endif | |
| 0, /* nb_remainder */ | |
| 0, /* nb_divmod */ | |
| 0, /* nb_power */ | |
| 0, /* nb_negative */ | |
| 0, /* nb_positive */ | |
| 0, /* nb_absolute */ | |
| (inquiry)bool_arrtype_nonzero, /* nb_nonzero / nb_bool */ | |
| 0, /* nb_invert */ | |
| 0, /* nb_lshift */ | |
| 0, /* nb_rshift */ | |
| (binaryfunc)bool_arrtype_and, /* nb_and */ | |
| (binaryfunc)bool_arrtype_xor, /* nb_xor */ | |
| (binaryfunc)bool_arrtype_or, /* nb_or */ | |
| #if defined(NPY_PY3K) | |
| #else | |
| 0, /* nb_coerce */ | |
| #endif | |
| 0, /* nb_int */ | |
| #if defined(NPY_PY3K) | |
| 0, /* nb_reserved */ | |
| #else | |
| 0, /* nb_long */ | |
| #endif | |
| 0, /* nb_float */ | |
| #if defined(NPY_PY3K) | |
| #else | |
| 0, /* nb_oct */ | |
| 0, /* nb_hex */ | |
| #endif | |
| /* Added in release 2.0 */ | |
| 0, /* nb_inplace_add */ | |
| 0, /* nb_inplace_subtract */ | |
| 0, /* nb_inplace_multiply */ | |
| #if defined(NPY_PY3K) | |
| #else | |
| 0, /* nb_inplace_divide */ | |
| #endif | |
| 0, /* nb_inplace_remainder */ | |
| 0, /* nb_inplace_power */ | |
| 0, /* nb_inplace_lshift */ | |
| 0, /* nb_inplace_rshift */ | |
| 0, /* nb_inplace_and */ | |
| 0, /* nb_inplace_xor */ | |
| 0, /* nb_inplace_or */ | |
| /* Added in release 2.2 */ | |
| /* The following require the Py_TPFLAGS_HAVE_CLASS flag */ | |
| 0, /* nb_floor_divide */ | |
| 0, /* nb_true_divide */ | |
| 0, /* nb_inplace_floor_divide */ | |
| 0, /* nb_inplace_true_divide */ | |
| /* Added in release 2.5 */ | |
| 0, /* nb_index */ | |
| }; | |
| static PyObject * | |
| void_arrtype_new(PyTypeObject *type, PyObject *args, PyObject *NPY_UNUSED(kwds)) | |
| { | |
| PyObject *obj, *arr; | |
| PyObject *new = NULL; | |
| if (!PyArg_ParseTuple(args, "O:void", &obj)) { | |
| return NULL; | |
| } | |
| /* | |
| * For a VOID scalar first see if obj is an integer or long | |
| * and create new memory of that size (filled with 0) for the scalar | |
| */ | |
| if (PyLong_Check(obj) || PyInt_Check(obj) || | |
| PyArray_IsScalar(obj, Integer) || | |
| (PyArray_Check(obj) && | |
| PyArray_NDIM((PyArrayObject *)obj)==0 && | |
| PyArray_ISINTEGER((PyArrayObject *)obj))) { | |
| #if defined(NPY_PY3K) | |
| new = Py_TYPE(obj)->tp_as_number->nb_int(obj); | |
| #else | |
| new = Py_TYPE(obj)->tp_as_number->nb_long(obj); | |
| #endif | |
| } | |
| if (new && PyLong_Check(new)) { | |
| PyObject *ret; | |
| char *destptr; | |
| npy_ulonglong memu = PyLong_AsUnsignedLongLong(new); | |
| Py_DECREF(new); | |
| if (PyErr_Occurred() || (memu > NPY_MAX_INT)) { | |
| PyErr_Clear(); | |
| PyErr_Format(PyExc_OverflowError, | |
| "size must be non-negative and not greater than %d", | |
| (int) NPY_MAX_INT); | |
| return NULL; | |
| } | |
| destptr = npy_alloc_cache_zero(memu); | |
| if (destptr == NULL) { | |
| return PyErr_NoMemory(); | |
| } | |
| ret = type->tp_alloc(type, 0); | |
| if (ret == NULL) { | |
| npy_free_cache(destptr, memu); | |
| return PyErr_NoMemory(); | |
| } | |
| ((PyVoidScalarObject *)ret)->obval = destptr; | |
| Py_SIZE((PyVoidScalarObject *)ret) = (int) memu; | |
| ((PyVoidScalarObject *)ret)->descr = | |
| PyArray_DescrNewFromType(NPY_VOID); | |
| ((PyVoidScalarObject *)ret)->descr->elsize = (int) memu; | |
| ((PyVoidScalarObject *)ret)->flags = NPY_ARRAY_BEHAVED | | |
| NPY_ARRAY_OWNDATA; | |
| ((PyVoidScalarObject *)ret)->base = NULL; | |
| return ret; | |
| } | |
| arr = PyArray_FROM_OTF(obj, NPY_VOID, NPY_ARRAY_FORCECAST); | |
| return PyArray_Return((PyArrayObject *)arr); | |
| } | |
| /**************** Define Hash functions ********************/ | |
| /**begin repeat | |
| * #lname = bool, ubyte, ushort# | |
| * #name = Bool,UByte, UShort# | |
| */ | |
| static npy_hash_t | |
| @lname@_arrtype_hash(PyObject *obj) | |
| { | |
| return (npy_hash_t)(((Py@name@ScalarObject *)obj)->obval); | |
| } | |
| /**end repeat**/ | |
| /**begin repeat | |
| * #lname = byte, short, uint# | |
| * #name = Byte, Short, UInt# | |
| */ | |
| static npy_hash_t | |
| @lname@_arrtype_hash(PyObject *obj) | |
| { | |
| npy_hash_t x = (npy_hash_t)(((Py@name@ScalarObject *)obj)->obval); | |
| if (x == -1) { | |
| x = -2; | |
| } | |
| return x; | |
| } | |
| /**end repeat**/ | |
| static npy_hash_t | |
| ulong_arrtype_hash(PyObject *obj) | |
| { | |
| PyObject * l = PyLong_FromUnsignedLong(((PyULongScalarObject*)obj)->obval); | |
| npy_hash_t x = PyObject_Hash(l); | |
| Py_DECREF(l); | |
| return x; | |
| } | |
| #if (NPY_SIZEOF_INT != NPY_SIZEOF_LONG) || defined(NPY_PY3K) | |
| static npy_hash_t | |
| int_arrtype_hash(PyObject *obj) | |
| { | |
| npy_hash_t x = (npy_hash_t)(((PyIntScalarObject *)obj)->obval); | |
| if (x == -1) { | |
| x = -2; | |
| } | |
| return x; | |
| } | |
| #endif | |
| #if defined(NPY_PY3K) | |
| static npy_hash_t | |
| long_arrtype_hash(PyObject *obj) | |
| { | |
| PyObject * l = PyLong_FromLong(((PyLongScalarObject*)obj)->obval); | |
| npy_hash_t x = PyObject_Hash(l); | |
| Py_DECREF(l); | |
| return x; | |
| } | |
| #endif | |
| /**begin repeat | |
| * #char = ,u# | |
| * #Char = ,U# | |
| * #Word = ,Unsigned# | |
| */ | |
| static NPY_INLINE npy_hash_t | |
| @char@longlong_arrtype_hash(PyObject *obj) | |
| { | |
| PyObject * l = PyLong_From@Word@LongLong( | |
| ((Py@Char@LongLongScalarObject*)obj)->obval); | |
| npy_hash_t x = PyObject_Hash(l); | |
| Py_DECREF(l); | |
| return x; | |
| } | |
| /**end repeat**/ | |
| /**begin repeat | |
| * #lname = datetime, timedelta# | |
| * #name = Datetime, Timedelta# | |
| */ | |
| #if NPY_SIZEOF_HASH_T==NPY_SIZEOF_DATETIME | |
| static npy_hash_t | |
| @lname@_arrtype_hash(PyObject *obj) | |
| { | |
| npy_hash_t x = (npy_hash_t)(((Py@name@ScalarObject *)obj)->obval); | |
| if (x == -1) { | |
| x = -2; | |
| } | |
| return x; | |
| } | |
| #elif NPY_SIZEOF_LONGLONG==NPY_SIZEOF_DATETIME | |
| static npy_hash_t | |
| @lname@_arrtype_hash(PyObject *obj) | |
| { | |
| npy_hash_t y; | |
| npy_longlong x = (((Py@name@ScalarObject *)obj)->obval); | |
| if ((x <= LONG_MAX)) { | |
| y = (npy_hash_t) x; | |
| } | |
| else { | |
| union Mask { | |
| long hashvals[2]; | |
| npy_longlong v; | |
| } both; | |
| both.v = x; | |
| y = both.hashvals[0] + (1000003)*both.hashvals[1]; | |
| } | |
| if (y == -1) { | |
| y = -2; | |
| } | |
| return y; | |
| } | |
| #endif | |
| /**end repeat**/ | |
| /* Wrong thing to do for longdouble, but....*/ | |
| /**begin repeat | |
| * #lname = float, longdouble# | |
| * #name = Float, LongDouble# | |
| */ | |
| static npy_hash_t | |
| @lname@_arrtype_hash(PyObject *obj) | |
| { | |
| return _Py_HashDouble((double) ((Py@name@ScalarObject *)obj)->obval); | |
| } | |
| /* borrowed from complex_hash */ | |
| static npy_hash_t | |
| c@lname@_arrtype_hash(PyObject *obj) | |
| { | |
| npy_hash_t hashreal, hashimag, combined; | |
| hashreal = _Py_HashDouble((double) | |
| (((PyC@name@ScalarObject *)obj)->obval).real); | |
| if (hashreal == -1) { | |
| return -1; | |
| } | |
| hashimag = _Py_HashDouble((double) | |
| (((PyC@name@ScalarObject *)obj)->obval).imag); | |
| if (hashimag == -1) { | |
| return -1; | |
| } | |
| combined = hashreal + 1000003 * hashimag; | |
| if (combined == -1) { | |
| combined = -2; | |
| } | |
| return combined; | |
| } | |
| /**end repeat**/ | |
| static npy_hash_t | |
| half_arrtype_hash(PyObject *obj) | |
| { | |
| return _Py_HashDouble(npy_half_to_double(((PyHalfScalarObject *)obj)->obval)); | |
| } | |
| static npy_hash_t | |
| object_arrtype_hash(PyObject *obj) | |
| { | |
| return PyObject_Hash(((PyObjectScalarObject *)obj)->obval); | |
| } | |
| /* we used to just hash the pointer */ | |
| /* now use tuplehash algorithm using voidtype_item to get the object | |
| */ | |
| static npy_hash_t | |
| void_arrtype_hash(PyObject *obj) | |
| { | |
| npy_hash_t x, y; | |
| Py_ssize_t len, n; | |
| PyVoidScalarObject *p; | |
| PyObject *element; | |
| npy_hash_t mult = 1000003L; | |
| x = 0x345678L; | |
| p = (PyVoidScalarObject *)obj; | |
| /* Cannot hash mutable void scalars */ | |
| if (p->flags & NPY_ARRAY_WRITEABLE) { | |
| PyErr_SetString(PyExc_TypeError, "unhashable type: 'writeable void-scalar'"); | |
| return -1; | |
| } | |
| len = voidtype_length(p); | |
| for (n=0; n < len; n++) { | |
| element = voidtype_item(p, n); | |
| y = PyObject_Hash(element); | |
| Py_DECREF(element); | |
| if (y == -1) | |
| return -1; | |
| x = (x ^ y) * mult; | |
| mult += (npy_hash_t)(82520L + len + len); | |
| } | |
| x += 97531L; | |
| if (x == -1) | |
| x = -2; | |
| return x; | |
| } | |
| /*object arrtype getattro and setattro */ | |
| static PyObject * | |
| object_arrtype_getattro(PyObjectScalarObject *obj, PyObject *attr) { | |
| PyObject *res; | |
| /* first look in object and then hand off to generic type */ | |
| res = PyObject_GenericGetAttr(obj->obval, attr); | |
| if (res) { | |
| return res; | |
| } | |
| PyErr_Clear(); | |
| return PyObject_GenericGetAttr((PyObject *)obj, attr); | |
| } | |
| static int | |
| object_arrtype_setattro(PyObjectScalarObject *obj, PyObject *attr, PyObject *val) { | |
| int res; | |
| /* first look in object and then hand off to generic type */ | |
| res = PyObject_GenericSetAttr(obj->obval, attr, val); | |
| if (res >= 0) { | |
| return res; | |
| } | |
| PyErr_Clear(); | |
| return PyObject_GenericSetAttr((PyObject *)obj, attr, val); | |
| } | |
| static PyObject * | |
| object_arrtype_concat(PyObjectScalarObject *self, PyObject *other) | |
| { | |
| return PySequence_Concat(self->obval, other); | |
| } | |
| static Py_ssize_t | |
| object_arrtype_length(PyObjectScalarObject *self) | |
| { | |
| return PyObject_Length(self->obval); | |
| } | |
| static PyObject * | |
| object_arrtype_repeat(PyObjectScalarObject *self, Py_ssize_t count) | |
| { | |
| return PySequence_Repeat(self->obval, count); | |
| } | |
| static PyObject * | |
| object_arrtype_subscript(PyObjectScalarObject *self, PyObject *key) | |
| { | |
| return PyObject_GetItem(self->obval, key); | |
| } | |
| static int | |
| object_arrtype_ass_subscript(PyObjectScalarObject *self, PyObject *key, | |
| PyObject *value) | |
| { | |
| return PyObject_SetItem(self->obval, key, value); | |
| } | |
| static int | |
| object_arrtype_contains(PyObjectScalarObject *self, PyObject *ob) | |
| { | |
| return PySequence_Contains(self->obval, ob); | |
| } | |
| static PyObject * | |
| object_arrtype_inplace_concat(PyObjectScalarObject *self, PyObject *o) | |
| { | |
| return PySequence_InPlaceConcat(self->obval, o); | |
| } | |
| static PyObject * | |
| object_arrtype_inplace_repeat(PyObjectScalarObject *self, Py_ssize_t count) | |
| { | |
| return PySequence_InPlaceRepeat(self->obval, count); | |
| } | |
| static PySequenceMethods object_arrtype_as_sequence = { | |
| (lenfunc)object_arrtype_length, /*sq_length*/ | |
| (binaryfunc)object_arrtype_concat, /*sq_concat*/ | |
| (ssizeargfunc)object_arrtype_repeat, /*sq_repeat*/ | |
| 0, /*sq_item*/ | |
| 0, /*sq_slice*/ | |
| 0, /* sq_ass_item */ | |
| 0, /* sq_ass_slice */ | |
| (objobjproc)object_arrtype_contains, /* sq_contains */ | |
| (binaryfunc)object_arrtype_inplace_concat, /* sq_inplace_concat */ | |
| (ssizeargfunc)object_arrtype_inplace_repeat, /* sq_inplace_repeat */ | |
| }; | |
| static PyMappingMethods object_arrtype_as_mapping = { | |
| (lenfunc)object_arrtype_length, | |
| (binaryfunc)object_arrtype_subscript, | |
| (objobjargproc)object_arrtype_ass_subscript, | |
| }; | |
| #if !defined(NPY_PY3K) | |
| static Py_ssize_t | |
| object_arrtype_getsegcount(PyObjectScalarObject *self, Py_ssize_t *lenp) | |
| { | |
| Py_ssize_t newlen; | |
| int cnt; | |
| PyBufferProcs *pb = Py_TYPE(self->obval)->tp_as_buffer; | |
| if (pb == NULL || | |
| pb->bf_getsegcount == NULL || | |
| (cnt = (*pb->bf_getsegcount)(self->obval, &newlen)) != 1) { | |
| return 0; | |
| } | |
| if (lenp) { | |
| *lenp = newlen; | |
| } | |
| return cnt; | |
| } | |
| static Py_ssize_t | |
| object_arrtype_getreadbuf(PyObjectScalarObject *self, Py_ssize_t segment, void **ptrptr) | |
| { | |
| PyBufferProcs *pb = Py_TYPE(self->obval)->tp_as_buffer; | |
| if (pb == NULL || | |
| pb->bf_getreadbuffer == NULL || | |
| pb->bf_getsegcount == NULL) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "expected a readable buffer object"); | |
| return -1; | |
| } | |
| return (*pb->bf_getreadbuffer)(self->obval, segment, ptrptr); | |
| } | |
| static Py_ssize_t | |
| object_arrtype_getwritebuf(PyObjectScalarObject *self, Py_ssize_t segment, void **ptrptr) | |
| { | |
| PyBufferProcs *pb = Py_TYPE(self->obval)->tp_as_buffer; | |
| if (pb == NULL || | |
| pb->bf_getwritebuffer == NULL || | |
| pb->bf_getsegcount == NULL) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "expected a writeable buffer object"); | |
| return -1; | |
| } | |
| return (*pb->bf_getwritebuffer)(self->obval, segment, ptrptr); | |
| } | |
| static Py_ssize_t | |
| object_arrtype_getcharbuf(PyObjectScalarObject *self, Py_ssize_t segment, | |
| constchar **ptrptr) | |
| { | |
| PyBufferProcs *pb = Py_TYPE(self->obval)->tp_as_buffer; | |
| if (pb == NULL || | |
| pb->bf_getcharbuffer == NULL || | |
| pb->bf_getsegcount == NULL) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "expected a character buffer object"); | |
| return -1; | |
| } | |
| return (*pb->bf_getcharbuffer)(self->obval, segment, ptrptr); | |
| } | |
| #endif | |
| static int | |
| object_arrtype_getbuffer(PyObjectScalarObject *self, Py_buffer *view, int flags) | |
| { | |
| PyBufferProcs *pb = Py_TYPE(self->obval)->tp_as_buffer; | |
| if (pb == NULL || pb->bf_getbuffer == NULL) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "expected a readable buffer object"); | |
| return -1; | |
| } | |
| return (*pb->bf_getbuffer)(self->obval, view, flags); | |
| } | |
| static void | |
| object_arrtype_releasebuffer(PyObjectScalarObject *self, Py_buffer *view) | |
| { | |
| PyBufferProcs *pb = Py_TYPE(self->obval)->tp_as_buffer; | |
| if (pb == NULL) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "expected a readable buffer object"); | |
| return; | |
| } | |
| if (pb->bf_releasebuffer != NULL) { | |
| (*pb->bf_releasebuffer)(self->obval, view); | |
| } | |
| } | |
| static PyBufferProcs object_arrtype_as_buffer = { | |
| #if !defined(NPY_PY3K) | |
| (readbufferproc)object_arrtype_getreadbuf, | |
| (writebufferproc)object_arrtype_getwritebuf, | |
| (segcountproc)object_arrtype_getsegcount, | |
| (charbufferproc)object_arrtype_getcharbuf, | |
| #endif | |
| (getbufferproc)object_arrtype_getbuffer, | |
| (releasebufferproc)object_arrtype_releasebuffer, | |
| }; | |
| static PyObject * | |
| object_arrtype_call(PyObjectScalarObject *obj, PyObject *args, PyObject *kwds) | |
| { | |
| return PyObject_Call(obj->obval, args, kwds); | |
| } | |
| NPY_NO_EXPORT PyTypeObject PyObjectArrType_Type = { | |
| #if defined(NPY_PY3K) | |
| PyVarObject_HEAD_INIT(NULL, 0) | |
| #else | |
| PyObject_HEAD_INIT(NULL) | |
| 0, /* ob_size */ | |
| #endif | |
| "numpy.object_", /* tp_name*/ | |
| sizeof(PyObjectScalarObject), /* tp_basicsize*/ | |
| 0, /* tp_itemsize */ | |
| (destructor)object_arrtype_dealloc, /* tp_dealloc */ | |
| 0, /* tp_print */ | |
| 0, /* tp_getattr */ | |
| 0, /* tp_setattr */ | |
| #if defined(NPY_PY3K) | |
| 0, /* tp_reserved */ | |
| #else | |
| 0, /* tp_compare */ | |
| #endif | |
| 0, /* tp_repr */ | |
| 0, /* tp_as_number */ | |
| &object_arrtype_as_sequence, /* tp_as_sequence */ | |
| &object_arrtype_as_mapping, /* tp_as_mapping */ | |
| 0, /* tp_hash */ | |
| (ternaryfunc)object_arrtype_call, /* tp_call */ | |
| 0, /* tp_str */ | |
| (getattrofunc)object_arrtype_getattro, /* tp_getattro */ | |
| (setattrofunc)object_arrtype_setattro, /* tp_setattro */ | |
| &object_arrtype_as_buffer, /* tp_as_buffer */ | |
| 0, /* tp_flags */ | |
| 0, /* tp_doc */ | |
| 0, /* tp_traverse */ | |
| 0, /* tp_clear */ | |
| 0, /* tp_richcompare */ | |
| 0, /* tp_weaklistoffset */ | |
| 0, /* tp_iter */ | |
| 0, /* tp_iternext */ | |
| 0, /* tp_methods */ | |
| 0, /* tp_members */ | |
| 0, /* tp_getset */ | |
| 0, /* tp_base */ | |
| 0, /* tp_dict */ | |
| 0, /* tp_descr_get */ | |
| 0, /* tp_descr_set */ | |
| 0, /* tp_dictoffset */ | |
| 0, /* tp_init */ | |
| 0, /* tp_alloc */ | |
| 0, /* tp_new */ | |
| 0, /* tp_free */ | |
| 0, /* tp_is_gc */ | |
| 0, /* tp_bases */ | |
| 0, /* tp_mro */ | |
| 0, /* tp_cache */ | |
| 0, /* tp_subclasses */ | |
| 0, /* tp_weaklist */ | |
| 0, /* tp_del */ | |
| 0, /* tp_version_tag */ | |
| }; | |
| static PyObject * | |
| gen_arrtype_subscript(PyObject *self, PyObject *key) | |
| { | |
| /* | |
| * Only [...], [...,<???>], [<???>, ...], | |
| * is allowed for indexing a scalar | |
| * | |
| * These return a new N-d array with a copy of | |
| * the data where N is the number of None's in <???>. | |
| */ | |
| PyObject *res, *ret; | |
| res = PyArray_FromScalar(self, NULL); | |
| ret = array_subscript((PyArrayObject *)res, key); | |
| Py_DECREF(res); | |
| if (ret == NULL) { | |
| PyErr_SetString(PyExc_IndexError, | |
| "invalid index to scalar variable."); | |
| } | |
| return ret; | |
| } | |
| #define NAME_bool "bool" | |
| #define NAME_void "void" | |
| #if defined(NPY_PY3K) | |
| #define NAME_string "bytes" | |
| #define NAME_unicode "str" | |
| #else | |
| #define NAME_string "string" | |
| #define NAME_unicode "unicode" | |
| #endif | |
| /**begin repeat | |
| * #name = bool, string, unicode, void# | |
| * #NAME = Bool, String, Unicode, Void# | |
| * #ex = _,_,_,# | |
| */ | |
| NPY_NO_EXPORT PyTypeObject Py@NAME@ArrType_Type = { | |
| #if defined(NPY_PY3K) | |
| PyVarObject_HEAD_INIT(NULL, 0) | |
| #else | |
| PyObject_HEAD_INIT(NULL) | |
| 0, /* ob_size */ | |
| #endif | |
| "numpy." NAME_@name@ "@ex@", /* tp_name*/ | |
| sizeof(Py@NAME@ScalarObject), /* tp_basicsize*/ | |
| 0, /* tp_itemsize */ | |
| 0, /* tp_dealloc */ | |
| 0, /* tp_print */ | |
| 0, /* tp_getattr */ | |
| 0, /* tp_setattr */ | |
| #if defined(NPY_PY3K) | |
| 0, /* tp_reserved */ | |
| #else | |
| 0, /* tp_compare */ | |
| #endif | |
| 0, /* tp_repr */ | |
| 0, /* tp_as_number */ | |
| 0, /* tp_as_sequence */ | |
| 0, /* tp_as_mapping */ | |
| 0, /* tp_hash */ | |
| 0, /* tp_call */ | |
| 0, /* tp_str */ | |
| 0, /* tp_getattro */ | |
| 0, /* tp_setattro */ | |
| 0, /* tp_as_buffer */ | |
| 0, /* tp_flags */ | |
| 0, /* tp_doc */ | |
| 0, /* tp_traverse */ | |
| 0, /* tp_clear */ | |
| 0, /* tp_richcompare */ | |
| 0, /* tp_weaklistoffset */ | |
| 0, /* tp_iter */ | |
| 0, /* tp_iternext */ | |
| 0, /* tp_methods */ | |
| 0, /* tp_members */ | |
| 0, /* tp_getset */ | |
| 0, /* tp_base */ | |
| 0, /* tp_dict */ | |
| 0, /* tp_descr_get */ | |
| 0, /* tp_descr_set */ | |
| 0, /* tp_dictoffset */ | |
| 0, /* tp_init */ | |
| 0, /* tp_alloc */ | |
| 0, /* tp_new */ | |
| 0, /* tp_free */ | |
| 0, /* tp_is_gc */ | |
| 0, /* tp_bases */ | |
| 0, /* tp_mro */ | |
| 0, /* tp_cache */ | |
| 0, /* tp_subclasses */ | |
| 0, /* tp_weaklist */ | |
| 0, /* tp_del */ | |
| 0, /* tp_version_tag */ | |
| }; | |
| /**end repeat**/ | |
| #undef NAME_bool | |
| #undef NAME_void | |
| #undef NAME_string | |
| #undef NAME_unicode | |
| /**begin repeat | |
| * #NAME = Byte, Short, Int, Long, LongLong, UByte, UShort, UInt, ULong, | |
| * ULongLong, Half, Float, Double, LongDouble, Datetime, Timedelta# | |
| * #name = int*5, uint*5, float*4, datetime, timedelta# | |
| * #CNAME = (CHAR, SHORT, INT, LONG, LONGLONG)*2, HALF, FLOAT, DOUBLE, | |
| * LONGDOUBLE, DATETIME, TIMEDELTA# | |
| */ | |
| #if NPY_BITSOF_@CNAME@ == 8 | |
| #define _THIS_SIZE "8" | |
| #elif NPY_BITSOF_@CNAME@ == 16 | |
| #define _THIS_SIZE "16" | |
| #elif NPY_BITSOF_@CNAME@ == 32 | |
| #define _THIS_SIZE "32" | |
| #elif NPY_BITSOF_@CNAME@ == 64 | |
| #define _THIS_SIZE "64" | |
| #elif NPY_BITSOF_@CNAME@ == 80 | |
| #define _THIS_SIZE "80" | |
| #elif NPY_BITSOF_@CNAME@ == 96 | |
| #define _THIS_SIZE "96" | |
| #elif NPY_BITSOF_@CNAME@ == 128 | |
| #define _THIS_SIZE "128" | |
| #elif NPY_BITSOF_@CNAME@ == 256 | |
| #define _THIS_SIZE "256" | |
| #endif | |
| NPY_NO_EXPORT PyTypeObject Py@NAME@ArrType_Type = { | |
| #if defined(NPY_PY3K) | |
| PyVarObject_HEAD_INIT(NULL, 0) | |
| #else | |
| PyObject_HEAD_INIT(NULL) | |
| 0, /* ob_size */ | |
| #endif | |
| "numpy.@name@" _THIS_SIZE, /* tp_name*/ | |
| sizeof(Py@NAME@ScalarObject), /* tp_basicsize*/ | |
| 0, /* tp_itemsize */ | |
| 0, /* tp_dealloc */ | |
| 0, /* tp_print */ | |
| 0, /* tp_getattr */ | |
| 0, /* tp_setattr */ | |
| #if defined(NPY_PY3K) | |
| 0, /* tp_reserved */ | |
| #else | |
| 0, /* tp_compare */ | |
| #endif | |
| 0, /* tp_repr */ | |
| 0, /* tp_as_number */ | |
| 0, /* tp_as_sequence */ | |
| 0, /* tp_as_mapping */ | |
| 0, /* tp_hash */ | |
| 0, /* tp_call */ | |
| 0, /* tp_str */ | |
| 0, /* tp_getattro */ | |
| 0, /* tp_setattro */ | |
| 0, /* tp_as_buffer */ | |
| 0, /* tp_flags */ | |
| 0, /* tp_doc */ | |
| 0, /* tp_traverse */ | |
| 0, /* tp_clear */ | |
| 0, /* tp_richcompare */ | |
| 0, /* tp_weaklistoffset */ | |
| 0, /* tp_iter */ | |
| 0, /* tp_iternext */ | |
| 0, /* tp_methods */ | |
| 0, /* tp_members */ | |
| 0, /* tp_getset */ | |
| 0, /* tp_base */ | |
| 0, /* tp_dict */ | |
| 0, /* tp_descr_get */ | |
| 0, /* tp_descr_set */ | |
| 0, /* tp_dictoffset */ | |
| 0, /* tp_init */ | |
| 0, /* tp_alloc */ | |
| 0, /* tp_new */ | |
| 0, /* tp_free */ | |
| 0, /* tp_is_gc */ | |
| 0, /* tp_bases */ | |
| 0, /* tp_mro */ | |
| 0, /* tp_cache */ | |
| 0, /* tp_subclasses */ | |
| 0, /* tp_weaklist */ | |
| 0, /* tp_del */ | |
| 0, /* tp_version_tag */ | |
| }; | |
| #undef _THIS_SIZE | |
| /**end repeat**/ | |
| static PyMappingMethods gentype_as_mapping = { | |
| NULL, | |
| (binaryfunc)gen_arrtype_subscript, | |
| NULL | |
| }; | |
| /**begin repeat | |
| * #NAME = CFloat, CDouble, CLongDouble# | |
| * #name = complex*3# | |
| * #CNAME = FLOAT, DOUBLE, LONGDOUBLE# | |
| */ | |
| #if NPY_BITSOF_@CNAME@ == 16 | |
| #define _THIS_SIZE "32" | |
| #elif NPY_BITSOF_@CNAME@ == 32 | |
| #define _THIS_SIZE "64" | |
| #elif NPY_BITSOF_@CNAME@ == 64 | |
| #define _THIS_SIZE "128" | |
| #elif NPY_BITSOF_@CNAME@ == 80 | |
| #define _THIS_SIZE "160" | |
| #elif NPY_BITSOF_@CNAME@ == 96 | |
| #define _THIS_SIZE "192" | |
| #elif NPY_BITSOF_@CNAME@ == 128 | |
| #define _THIS_SIZE "256" | |
| #elif NPY_BITSOF_@CNAME@ == 256 | |
| #define _THIS_SIZE "512" | |
| #endif | |
| NPY_NO_EXPORT PyTypeObject Py@NAME@ArrType_Type = { | |
| #if defined(NPY_PY3K) | |
| PyVarObject_HEAD_INIT(0, 0) | |
| #else | |
| PyObject_HEAD_INIT(0) | |
| 0, /* ob_size */ | |
| #endif | |
| "numpy.@name@" _THIS_SIZE, /* tp_name*/ | |
| sizeof(Py@NAME@ScalarObject), /* tp_basicsize*/ | |
| 0, /* tp_itemsize*/ | |
| 0, /* tp_dealloc*/ | |
| 0, /* tp_print*/ | |
| 0, /* tp_getattr*/ | |
| 0, /* tp_setattr*/ | |
| #if defined(NPY_PY3K) | |
| 0, /* tp_reserved */ | |
| #else | |
| 0, /* tp_compare */ | |
| #endif | |
| 0, /* tp_repr*/ | |
| 0, /* tp_as_number*/ | |
| 0, /* tp_as_sequence*/ | |
| 0, /* tp_as_mapping*/ | |
| 0, /* tp_hash */ | |
| 0, /* tp_call*/ | |
| 0, /* tp_str*/ | |
| 0, /* tp_getattro*/ | |
| 0, /* tp_setattro*/ | |
| 0, /* tp_as_buffer*/ | |
| Py_TPFLAGS_DEFAULT, /* tp_flags*/ | |
| 0, /* tp_doc */ | |
| 0, /* tp_traverse */ | |
| 0, /* tp_clear */ | |
| 0, /* tp_richcompare */ | |
| 0, /* tp_weaklistoffset */ | |
| 0, /* tp_iter */ | |
| 0, /* tp_iternext */ | |
| 0, /* tp_methods */ | |
| 0, /* tp_members */ | |
| 0, /* tp_getset */ | |
| 0, /* tp_base */ | |
| 0, /* tp_dict */ | |
| 0, /* tp_descr_get */ | |
| 0, /* tp_descr_set */ | |
| 0, /* tp_dictoffset */ | |
| 0, /* tp_init */ | |
| 0, /* tp_alloc */ | |
| 0, /* tp_new */ | |
| 0, /* tp_free */ | |
| 0, /* tp_is_gc */ | |
| 0, /* tp_bases */ | |
| 0, /* tp_mro */ | |
| 0, /* tp_cache */ | |
| 0, /* tp_subclasses */ | |
| 0, /* tp_weaklist */ | |
| 0, /* tp_del */ | |
| 0, /* tp_version_tag */ | |
| }; | |
| #undef _THIS_SIZE | |
| /**end repeat**/ | |
| /* | |
| * This table maps the built-in type numbers to their scalar | |
| * type numbers. Note that signed integers are mapped to INTNEG_SCALAR, | |
| * which is different than what PyArray_ScalarKind returns. | |
| */ | |
| NPY_NO_EXPORT signed char | |
| _npy_scalar_kinds_table[NPY_NTYPES]; | |
| /* | |
| * This table maps a scalar kind (excluding NPY_NOSCALAR) | |
| * to the smallest type number of that kind. | |
| */ | |
| NPY_NO_EXPORT signed char | |
| _npy_smallest_type_of_kind_table[NPY_NSCALARKINDS]; | |
| /* | |
| * This table gives the type of the same kind, but next in the sequence | |
| * of sizes. | |
| */ | |
| NPY_NO_EXPORT signed char | |
| _npy_next_larger_type_table[NPY_NTYPES]; | |
| /* | |
| * This table describes safe casting for small type numbers, | |
| * and is used by PyArray_CanCastSafely. | |
| */ | |
| NPY_NO_EXPORT unsigned char | |
| _npy_can_cast_safely_table[NPY_NTYPES][NPY_NTYPES]; | |
| /* | |
| * This table gives the smallest-size and smallest-kind type to which | |
| * the input types may be safely cast, according to _npy_can_cast_safely. | |
| */ | |
| NPY_NO_EXPORT signed char | |
| _npy_type_promotion_table[NPY_NTYPES][NPY_NTYPES]; | |
| NPY_NO_EXPORT void | |
| initialize_casting_tables(void) | |
| { | |
| int i, j; | |
| _npy_smallest_type_of_kind_table[NPY_BOOL_SCALAR] = NPY_BOOL; | |
| _npy_smallest_type_of_kind_table[NPY_INTPOS_SCALAR] = NPY_UBYTE; | |
| _npy_smallest_type_of_kind_table[NPY_INTNEG_SCALAR] = NPY_BYTE; | |
| _npy_smallest_type_of_kind_table[NPY_FLOAT_SCALAR] = NPY_HALF; | |
| _npy_smallest_type_of_kind_table[NPY_COMPLEX_SCALAR] = NPY_CFLOAT; | |
| _npy_smallest_type_of_kind_table[NPY_OBJECT_SCALAR] = NPY_OBJECT; | |
| /* Default for built-in types is object scalar */ | |
| memset(_npy_scalar_kinds_table, NPY_OBJECT_SCALAR, | |
| sizeof(_npy_scalar_kinds_table)); | |
| /* Default for next largest type is -1, signalling no bigger */ | |
| memset(_npy_next_larger_type_table, -1, | |
| sizeof(_npy_next_larger_type_table)); | |
| /* Compile-time loop of scalar kinds */ | |
| /**begin repeat | |
| * #NAME = BOOL, | |
| * BYTE, UBYTE, SHORT, USHORT, INT, UINT, | |
| * LONG, ULONG, LONGLONG, ULONGLONG, | |
| * HALF, FLOAT, DOUBLE, LONGDOUBLE, | |
| * CFLOAT, CDOUBLE, CLONGDOUBLE# | |
| * #BIGGERTYPE = -1, | |
| * NPY_SHORT, NPY_USHORT, NPY_INT, NPY_UINT, NPY_LONG, NPY_ULONG, | |
| * NPY_LONGLONG, NPY_ULONGLONG, -1, -1, | |
| * NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE, -1, | |
| * NPY_CDOUBLE, NPY_CLONGDOUBLE, -1# | |
| * #SCKIND = BOOL, | |
| * (INTNEG, INTPOS)*5, | |
| * FLOAT*4, | |
| * COMPLEX*3# | |
| */ | |
| _npy_scalar_kinds_table[NPY_@NAME@] = NPY_@SCKIND@_SCALAR; | |
| _npy_next_larger_type_table[NPY_@NAME@] = @BIGGERTYPE@; | |
| /**end repeat**/ | |
| memset(_npy_can_cast_safely_table, 0, sizeof(_npy_can_cast_safely_table)); | |
| for (i = 0; i < NPY_NTYPES; ++i) { | |
| /* Identity */ | |
| _npy_can_cast_safely_table[i][i] = 1; | |
| if (i != NPY_DATETIME) { | |
| /* | |
| * Bool -> <Anything> except datetime (since | |
| * it conceptually has no zero) | |
| */ | |
| _npy_can_cast_safely_table[NPY_BOOL][i] = 1; | |
| } | |
| /* <Anything> -> Object */ | |
| _npy_can_cast_safely_table[i][NPY_OBJECT] = 1; | |
| /* <Anything> -> Void */ | |
| _npy_can_cast_safely_table[i][NPY_VOID] = 1; | |
| } | |
| _npy_can_cast_safely_table[NPY_STRING][NPY_UNICODE] = 1; | |
| _npy_can_cast_safely_table[NPY_BOOL][NPY_TIMEDELTA] = 1; | |
| #ifndef NPY_SIZEOF_BYTE | |
| #define NPY_SIZEOF_BYTE 1 | |
| #endif | |
| /* Compile-time loop of casting rules */ | |
| /**begin repeat | |
| * #FROM_NAME = BYTE, UBYTE, SHORT, USHORT, INT, UINT, | |
| * LONG, ULONG, LONGLONG, ULONGLONG, | |
| * HALF, FLOAT, DOUBLE, LONGDOUBLE, | |
| * CFLOAT, CDOUBLE, CLONGDOUBLE# | |
| * #FROM_BASENAME = BYTE, BYTE, SHORT, SHORT, INT, INT, | |
| * LONG, LONG, LONGLONG, LONGLONG, | |
| * HALF, FLOAT, DOUBLE, LONGDOUBLE, | |
| * FLOAT, DOUBLE, LONGDOUBLE# | |
| * #from_isint = 1, 0, 1, 0, 1, 0, 1, 0, | |
| * 1, 0, 0, 0, 0, 0, | |
| * 0, 0, 0# | |
| * #from_isuint = 0, 1, 0, 1, 0, 1, 0, 1, | |
| * 0, 1, 0, 0, 0, 0, | |
| * 0, 0, 0# | |
| * #from_isfloat = 0, 0, 0, 0, 0, 0, 0, 0, | |
| * 0, 0, 1, 1, 1, 1, | |
| * 0, 0, 0# | |
| * #from_iscomplex = 0, 0, 0, 0, 0, 0, 0, 0, | |
| * 0, 0, 0, 0, 0, 0, | |
| * 1, 1, 1# | |
| */ | |
| #define _FROM_BSIZE NPY_SIZEOF_@FROM_BASENAME@ | |
| #define _FROM_NUM (NPY_@FROM_NAME@) | |
| _npy_can_cast_safely_table[_FROM_NUM][NPY_STRING] = 1; | |
| _npy_can_cast_safely_table[_FROM_NUM][NPY_UNICODE] = 1; | |
| /* Allow casts from any integer to the TIMEDELTA type */ | |
| #if @from_isint@ || @from_isuint@ | |
| _npy_can_cast_safely_table[_FROM_NUM][NPY_TIMEDELTA] = 1; | |
| #endif | |
| /**begin repeat1 | |
| * #TO_NAME = BYTE, UBYTE, SHORT, USHORT, INT, UINT, | |
| * LONG, ULONG, LONGLONG, ULONGLONG, | |
| * HALF, FLOAT, DOUBLE, LONGDOUBLE, | |
| * CFLOAT, CDOUBLE, CLONGDOUBLE# | |
| * #TO_BASENAME = BYTE, BYTE, SHORT, SHORT, INT, INT, | |
| * LONG, LONG, LONGLONG, LONGLONG, | |
| * HALF, FLOAT, DOUBLE, LONGDOUBLE, | |
| * FLOAT, DOUBLE, LONGDOUBLE# | |
| * #to_isint = 1, 0, 1, 0, 1, 0, 1, 0, | |
| * 1, 0, 0, 0, 0, 0, | |
| * 0, 0, 0# | |
| * #to_isuint = 0, 1, 0, 1, 0, 1, 0, 1, | |
| * 0, 1, 0, 0, 0, 0, | |
| * 0, 0, 0# | |
| * #to_isfloat = 0, 0, 0, 0, 0, 0, 0, 0, | |
| * 0, 0, 1, 1, 1, 1, | |
| * 0, 0, 0# | |
| * #to_iscomplex = 0, 0, 0, 0, 0, 0, 0, 0, | |
| * 0, 0, 0, 0, 0, 0, | |
| * 1, 1, 1# | |
| */ | |
| #define _TO_BSIZE NPY_SIZEOF_@TO_BASENAME@ | |
| #define _TO_NUM (NPY_@TO_NAME@) | |
| /* | |
| * NOTE: _FROM_BSIZE and _TO_BSIZE are the sizes of the "base type" | |
| * which is the same as the size of the type except for | |
| * complex, where it is the size of the real type. | |
| */ | |
| #if @from_isint@ | |
| # if @to_isint@ && (_TO_BSIZE >= _FROM_BSIZE) | |
| /* int -> int */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # elif @to_isfloat@ && (_FROM_BSIZE < 8) && (_TO_BSIZE > _FROM_BSIZE) | |
| /* int -> float */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # elif @to_isfloat@ && (_FROM_BSIZE >= 8) && (_TO_BSIZE >= _FROM_BSIZE) | |
| /* int -> float */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # elif @to_iscomplex@ && (_FROM_BSIZE < 8) && (_TO_BSIZE > _FROM_BSIZE) | |
| /* int -> complex */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # elif @to_iscomplex@ && (_FROM_BSIZE >= 8) && (_TO_BSIZE >= _FROM_BSIZE) | |
| /* int -> complex */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # endif | |
| #elif @from_isuint@ | |
| # if @to_isint@ && (_TO_BSIZE > _FROM_BSIZE) | |
| /* uint -> int */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # elif @to_isuint@ && (_TO_BSIZE >= _FROM_BSIZE) | |
| /* uint -> uint */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # elif @to_isfloat@ && (_FROM_BSIZE < 8) && (_TO_BSIZE > _FROM_BSIZE) | |
| /* uint -> float */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # elif @to_isfloat@ && (_FROM_BSIZE >= 8) && (_TO_BSIZE >= _FROM_BSIZE) | |
| /* uint -> float */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # elif @to_iscomplex@ && (_FROM_BSIZE < 8) && (_TO_BSIZE > _FROM_BSIZE) | |
| /* uint -> complex */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # elif @to_iscomplex@ && (_FROM_BSIZE >= 8) && (_TO_BSIZE >= _FROM_BSIZE) | |
| /* uint -> complex */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # endif | |
| #elif @from_isfloat@ | |
| # if @to_isfloat@ && (_TO_BSIZE >= _FROM_BSIZE) | |
| /* float -> float */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # elif @to_iscomplex@ && (_TO_BSIZE >= _FROM_BSIZE) | |
| /* float -> complex */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # endif | |
| #elif @from_iscomplex@ | |
| # if @to_iscomplex@ && (_TO_BSIZE >= _FROM_BSIZE) | |
| /* complex -> complex */ | |
| _npy_can_cast_safely_table[_FROM_NUM][_TO_NUM] = 1; | |
| # endif | |
| #endif | |
| #undef _TO_NUM | |
| #undef _TO_BSIZE | |
| /**end repeat1**/ | |
| #undef _FROM_NUM | |
| #undef _FROM_BSIZE | |
| /**end repeat**/ | |
| /* | |
| * Now that the _can_cast_safely table is finished, we can | |
| * use it to build the _type_promotion table | |
| */ | |
| for (i = 0; i < NPY_NTYPES; ++i) { | |
| _npy_type_promotion_table[i][i] = i; | |
| /* Don't let number promote to string/unicode/void/datetime/timedelta */ | |
| if (i == NPY_STRING || i == NPY_UNICODE || i == NPY_VOID || | |
| i == NPY_DATETIME || i == NPY_TIMEDELTA) { | |
| /* Promoting these types requires examining their contents */ | |
| _npy_type_promotion_table[i][i] = -1; | |
| for (j = i + 1; j < NPY_NTYPES; ++j) { | |
| _npy_type_promotion_table[i][j] = -1; | |
| _npy_type_promotion_table[j][i] = -1; | |
| } | |
| /* Except they can convert to OBJECT */ | |
| _npy_type_promotion_table[i][NPY_OBJECT] = NPY_OBJECT; | |
| _npy_type_promotion_table[NPY_OBJECT][i] = NPY_OBJECT; | |
| } | |
| else { | |
| for (j = i + 1; j < NPY_NTYPES; ++j) { | |
| /* Don't let number promote to string/unicode/void */ | |
| if (j == NPY_STRING || j == NPY_UNICODE || j == NPY_VOID) { | |
| _npy_type_promotion_table[i][j] = -1; | |
| _npy_type_promotion_table[j][i] = -1; | |
| } | |
| else if (_npy_can_cast_safely_table[i][j]) { | |
| _npy_type_promotion_table[i][j] = j; | |
| _npy_type_promotion_table[j][i] = j; | |
| } | |
| else if (_npy_can_cast_safely_table[j][i]) { | |
| _npy_type_promotion_table[i][j] = i; | |
| _npy_type_promotion_table[j][i] = i; | |
| } | |
| else { | |
| int k, iskind, jskind, skind; | |
| iskind = _npy_scalar_kinds_table[i]; | |
| jskind = _npy_scalar_kinds_table[j]; | |
| /* If there's no kind (void/string/etc) */ | |
| if (iskind == NPY_NOSCALAR || jskind == NPY_NOSCALAR) { | |
| k = -1; | |
| } | |
| else { | |
| /* Start with the type of larger kind */ | |
| if (iskind > jskind) { | |
| skind = iskind; | |
| k = i; | |
| } | |
| else { | |
| skind = jskind; | |
| k = j; | |
| } | |
| for (;;) { | |
| /* Try the next larger type of this kind */ | |
| k = _npy_next_larger_type_table[k]; | |
| /* If there is no larger, try a larger kind */ | |
| if (k < 0) { | |
| ++skind; | |
| /* Use -1 to signal no promoted type found */ | |
| if (skind < NPY_NSCALARKINDS) { | |
| k = _npy_smallest_type_of_kind_table[skind]; | |
| } | |
| else { | |
| k = -1; | |
| break; | |
| } | |
| } | |
| if (_npy_can_cast_safely_table[i][k] && | |
| _npy_can_cast_safely_table[j][k]) { | |
| break; | |
| } | |
| } | |
| } | |
| _npy_type_promotion_table[i][j] = k; | |
| _npy_type_promotion_table[j][i] = k; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| #ifndef NPY_PY3K | |
| /* | |
| * In python2, the `float` and `complex` types still implement the obsolete | |
| * "tp_print" method, which uses CPython's float-printing routines to print the | |
| * float. Numpy's float_/cfloat inherit from Python float/complex, but | |
| * override its tp_repr and tp_str methods. In order to avoid an inconsistency | |
| * with the inherited tp_print, we need to override it too. | |
| * | |
| * In python3 the tp_print method is reserved/unused. | |
| */ | |
| static int | |
| doubletype_print(PyObject *o, FILE *fp, int flags) | |
| { | |
| int ret; | |
| PyObject *to_print; | |
| if (flags & Py_PRINT_RAW) { | |
| to_print = PyObject_Str(o); | |
| } | |
| else { | |
| to_print = PyObject_Repr(o); | |
| } | |
| if (to_print == NULL) { | |
| return -1; | |
| } | |
| ret = PyObject_Print(to_print, fp, Py_PRINT_RAW); | |
| Py_DECREF(to_print); | |
| return ret; | |
| } | |
| #endif | |
| static PyNumberMethods longdoubletype_as_number; | |
| static PyNumberMethods clongdoubletype_as_number; | |
| static void init_basetypes(void); | |
| NPY_NO_EXPORT void | |
| initialize_numeric_types(void) | |
| { | |
| init_basetypes(); | |
| PyGenericArrType_Type.tp_dealloc = (destructor)gentype_dealloc; | |
| PyGenericArrType_Type.tp_as_number = &gentype_as_number; | |
| PyGenericArrType_Type.tp_as_buffer = &gentype_as_buffer; | |
| PyGenericArrType_Type.tp_as_mapping = &gentype_as_mapping; | |
| PyGenericArrType_Type.tp_flags = BASEFLAGS; | |
| PyGenericArrType_Type.tp_methods = gentype_methods; | |
| PyGenericArrType_Type.tp_getset = gentype_getsets; | |
| PyGenericArrType_Type.tp_new = NULL; | |
| PyGenericArrType_Type.tp_alloc = gentype_alloc; | |
| PyGenericArrType_Type.tp_free = (freefunc)gentype_free; | |
| PyGenericArrType_Type.tp_richcompare = gentype_richcompare; | |
| PyBoolArrType_Type.tp_as_number = &bool_arrtype_as_number; | |
| /* | |
| * need to add dummy versions with filled-in nb_index | |
| * in-order for PyType_Ready to fill in .__index__() method | |
| * also fill array_type_as_number struct with reasonable defaults | |
| */ | |
| /**begin repeat | |
| * #name = byte, short, int, long, longlong, ubyte, ushort, | |
| * uint, ulong, ulonglong# | |
| * #NAME = Byte, Short, Int, Long, LongLong, UByte, UShort, | |
| * UInt, ULong, ULongLong# | |
| */ | |
| @name@_arrtype_as_number = gentype_as_number; | |
| Py@NAME@ArrType_Type.tp_as_number = &@name@_arrtype_as_number; | |
| Py@NAME@ArrType_Type.tp_as_number->nb_index = (unaryfunc)@name@_index; | |
| /**end repeat**/ | |
| /**begin repeat | |
| * #name = half, float, double, longdouble, | |
| * cfloat, cdouble, clongdouble# | |
| * #NAME = Half, Float, Double, LongDouble, | |
| * CFloat, CDouble, CLongDouble# | |
| */ | |
| @name@_arrtype_as_number = gentype_as_number; | |
| Py@NAME@ArrType_Type.tp_as_number = &@name@_arrtype_as_number; | |
| /**end repeat**/ | |
| #ifndef NPY_PY3K | |
| PyDoubleArrType_Type.tp_print = &doubletype_print; | |
| PyCDoubleArrType_Type.tp_print = &doubletype_print; | |
| #endif | |
| PyBoolArrType_Type.tp_as_number->nb_index = (unaryfunc)bool_index; | |
| PyStringArrType_Type.tp_alloc = NULL; | |
| PyStringArrType_Type.tp_free = NULL; | |
| PyStringArrType_Type.tp_repr = stringtype_repr; | |
| PyStringArrType_Type.tp_str = stringtype_str; | |
| PyUnicodeArrType_Type.tp_repr = unicodetype_repr; | |
| PyUnicodeArrType_Type.tp_str = unicodetype_str; | |
| PyVoidArrType_Type.tp_methods = voidtype_methods; | |
| PyVoidArrType_Type.tp_getset = voidtype_getsets; | |
| PyVoidArrType_Type.tp_as_mapping = &voidtype_as_mapping; | |
| PyVoidArrType_Type.tp_as_sequence = &voidtype_as_sequence; | |
| PyVoidArrType_Type.tp_repr = voidtype_repr; | |
| PyVoidArrType_Type.tp_str = voidtype_str; | |
| PyIntegerArrType_Type.tp_getset = inttype_getsets; | |
| /**begin repeat | |
| * #NAME= Number, Integer, SignedInteger, UnsignedInteger, Inexact, | |
| * Floating, ComplexFloating, Flexible, Character# | |
| */ | |
| Py@NAME@ArrType_Type.tp_flags = BASEFLAGS; | |
| /**end repeat**/ | |
| /**begin repeat | |
| * #name = bool, byte, short, int, long, longlong, ubyte, ushort, uint, | |
| * ulong, ulonglong, half, float, double, longdouble, cfloat, | |
| * cdouble, clongdouble, string, unicode, void, object, datetime, | |
| * timedelta# | |
| * #NAME = Bool, Byte, Short, Int, Long, LongLong, UByte, UShort, UInt, | |
| * ULong, ULongLong, Half, Float, Double, LongDouble, CFloat, | |
| * CDouble, CLongDouble, String, Unicode, Void, Object, Datetime, | |
| * Timedelta# | |
| */ | |
| Py@NAME@ArrType_Type.tp_flags = BASEFLAGS; | |
| Py@NAME@ArrType_Type.tp_new = @name@_arrtype_new; | |
| Py@NAME@ArrType_Type.tp_richcompare = gentype_richcompare; | |
| /**end repeat**/ | |
| /**begin repeat | |
| * #name = bool, byte, short, ubyte, ushort, uint, ulong, ulonglong, | |
| * half, float, longdouble, cfloat, clongdouble, void, object, | |
| * datetime, timedelta# | |
| * #NAME = Bool, Byte, Short, UByte, UShort, UInt, ULong, ULongLong, | |
| * Half, Float, LongDouble, CFloat, CLongDouble, Void, Object, | |
| * Datetime, Timedelta# | |
| */ | |
| Py@NAME@ArrType_Type.tp_hash = @name@_arrtype_hash; | |
| /**end repeat**/ | |
| /**begin repeat | |
| * #name = cfloat, clongdouble# | |
| * #NAME = CFloat, CLongDouble# | |
| */ | |
| Py@NAME@ArrType_Type.tp_methods = @name@type_methods; | |
| /**end repeat**/ | |
| #if (NPY_SIZEOF_INT != NPY_SIZEOF_LONG) || defined(NPY_PY3K) | |
| /* We won't be inheriting from Python Int type. */ | |
| PyIntArrType_Type.tp_hash = int_arrtype_hash; | |
| #endif | |
| #if defined(NPY_PY3K) | |
| /* We won't be inheriting from Python Int type. */ | |
| PyLongArrType_Type.tp_hash = long_arrtype_hash; | |
| #endif | |
| #if (NPY_SIZEOF_LONG != NPY_SIZEOF_LONGLONG) || defined(NPY_PY3K) | |
| /* We won't be inheriting from Python Int type. */ | |
| PyLongLongArrType_Type.tp_hash = longlong_arrtype_hash; | |
| #endif | |
| /**begin repeat | |
| * #name = repr, str# | |
| */ | |
| PyHalfArrType_Type.tp_@name@ = halftype_@name@; | |
| PyFloatArrType_Type.tp_@name@ = floattype_@name@; | |
| PyCFloatArrType_Type.tp_@name@ = cfloattype_@name@; | |
| PyDoubleArrType_Type.tp_@name@ = doubletype_@name@; | |
| PyCDoubleArrType_Type.tp_@name@ = cdoubletype_@name@; | |
| PyDatetimeArrType_Type.tp_@name@ = datetimetype_@name@; | |
| PyTimedeltaArrType_Type.tp_@name@ = timedeltatype_@name@; | |
| /**end repeat**/ | |
| /**begin repeat | |
| * #Type = Bool, Byte, UByte, Short, UShort, Int, UInt, Long, | |
| * ULong, LongLong, ULongLong# | |
| */ | |
| /* both str/repr use genint_type_str to avoid trailing "L" of longs */ | |
| Py@Type@ArrType_Type.tp_str = genint_type_str; | |
| Py@Type@ArrType_Type.tp_repr = genint_type_str; | |
| /**end repeat**/ | |
| /**begin repeat | |
| * #char = ,c# | |
| * #CHAR = ,C# | |
| */ | |
| /* | |
| * These need to be coded specially because longdouble/clongdouble getitem | |
| * does not return a normal Python type | |
| */ | |
| @char@longdoubletype_as_number.nb_float = @char@longdoubletype_float; | |
| #if defined(NPY_PY3K) | |
| @char@longdoubletype_as_number.nb_int = @char@longdoubletype_long; | |
| #else | |
| @char@longdoubletype_as_number.nb_int = @char@longdoubletype_int; | |
| @char@longdoubletype_as_number.nb_long = @char@longdoubletype_long; | |
| @char@longdoubletype_as_number.nb_hex = @char@longdoubletype_hex; | |
| @char@longdoubletype_as_number.nb_oct = @char@longdoubletype_oct; | |
| #endif | |
| Py@CHAR@LongDoubleArrType_Type.tp_as_number = &@char@longdoubletype_as_number; | |
| Py@CHAR@LongDoubleArrType_Type.tp_repr = @char@longdoubletype_repr; | |
| Py@CHAR@LongDoubleArrType_Type.tp_str = @char@longdoubletype_str; | |
| /**end repeat**/ | |
| PyStringArrType_Type.tp_itemsize = sizeof(char); | |
| PyVoidArrType_Type.tp_dealloc = (destructor) void_dealloc; | |
| PyArrayIter_Type.tp_iter = PyObject_SelfIter; | |
| PyArrayMapIter_Type.tp_iter = PyObject_SelfIter; | |
| } | |
| typedef struct { | |
| PyTypeObject * type; | |
| int typenum; | |
| } scalar_type; | |
| static scalar_type typeobjects[] = { | |
| {&PyBoolArrType_Type, NPY_BOOL}, | |
| {&PyByteArrType_Type, NPY_BYTE}, | |
| {&PyUByteArrType_Type, NPY_UBYTE}, | |
| {&PyShortArrType_Type, NPY_SHORT}, | |
| {&PyUShortArrType_Type, NPY_USHORT}, | |
| {&PyIntArrType_Type, NPY_INT}, | |
| {&PyUIntArrType_Type, NPY_UINT}, | |
| {&PyLongArrType_Type, NPY_LONG}, | |
| {&PyULongArrType_Type, NPY_ULONG}, | |
| {&PyLongLongArrType_Type, NPY_LONGLONG}, | |
| {&PyULongLongArrType_Type, NPY_ULONGLONG}, | |
| {&PyFloatArrType_Type, NPY_FLOAT}, | |
| {&PyDoubleArrType_Type, NPY_DOUBLE}, | |
| {&PyLongDoubleArrType_Type, NPY_LONGDOUBLE}, | |
| {&PyCFloatArrType_Type, NPY_CFLOAT}, | |
| {&PyCDoubleArrType_Type, NPY_CDOUBLE}, | |
| {&PyCLongDoubleArrType_Type, NPY_CLONGDOUBLE}, | |
| {&PyObjectArrType_Type, NPY_OBJECT}, | |
| {&PyStringArrType_Type, NPY_STRING}, | |
| {&PyUnicodeArrType_Type, NPY_UNICODE}, | |
| {&PyVoidArrType_Type, NPY_VOID}, | |
| {&PyDatetimeArrType_Type, NPY_DATETIME}, | |
| {&PyTimedeltaArrType_Type, NPY_TIMEDELTA}, | |
| {&PyHalfArrType_Type, NPY_HALF} | |
| }; | |
| static int compare_types(const void * a_, const void * b_) | |
| { | |
| const PyTypeObject * a = ((const scalar_type *)a_)->type; | |
| const PyTypeObject * b = ((const scalar_type *)b_)->type; | |
| if (a < b) { | |
| return -1; | |
| } | |
| else if (a > b) { | |
| return 1; | |
| } | |
| return 0; | |
| } | |
| static void init_basetypes(void) | |
| { | |
| qsort(typeobjects, sizeof(typeobjects) / sizeof(typeobjects[0]), | |
| sizeof(typeobjects[0]), | |
| compare_types); | |
| } | |
| NPY_NO_EXPORT int | |
| get_typeobj_idx(PyTypeObject * obj) | |
| { | |
| npy_intp imin = 0, imax = sizeof(typeobjects) / sizeof(typeobjects[0]) - 1; | |
| while (imax >= imin) | |
| { | |
| npy_intp imid = ((imax - imin) / 2) + imin; | |
| if(typeobjects[imid].type == obj) { | |
| return imid; | |
| } | |
| else if (typeobjects[imid].type < obj) { | |
| imin = imid + 1; | |
| } | |
| else { | |
| imax = imid - 1; | |
| } | |
| } | |
| return -1; | |
| } | |
| NPY_NO_EXPORT int | |
| is_anyscalar_exact(PyObject *obj) | |
| { | |
| return get_typeobj_idx(Py_TYPE(obj)) >= 0; | |
| } | |
| NPY_NO_EXPORT int | |
| _typenum_fromtypeobj(PyObject *type, int user) | |
| { | |
| int typenum, i; | |
| typenum = NPY_NOTYPE; | |
| i = get_typeobj_idx((PyTypeObject*)type); | |
| if (i >= 0) { | |
| typenum = typeobjects[i].typenum; | |
| } | |
| if (!user) { | |
| return typenum; | |
| } | |
| /* Search any registered types */ | |
| i = 0; | |
| while (i < NPY_NUMUSERTYPES) { | |
| if (type == (PyObject *)(userdescrs[i]->typeobj)) { | |
| typenum = i + NPY_USERDEF; | |
| break; | |
| } | |
| i++; | |
| } | |
| return typenum; | |
| } |