/* -*- 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 <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
static PyObject *
gentype_multiply(PyObject *m1, PyObject *m2)
{
npy_intp repeat;
/*
* If the other object supports sequence repeat and not number multiply
* we should call sequence repeat to support e.g. list repeat by numpy
* scalars (they may be converted to ndarray otherwise).
* 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) &&
((Py_TYPE(m1)->tp_as_sequence != NULL) &&
(Py_TYPE(m1)->tp_as_sequence->sq_repeat != NULL)) &&
((Py_TYPE(m1)->tp_as_number == NULL) ||
(Py_TYPE(m1)->tp_as_number->nb_multiply == NULL))) {
/* Try to convert m2 to an int and try sequence repeat */
repeat = PyArray_PyIntAsIntp(m2);
if (error_converting(repeat)) {
return NULL;
}
/* Note that npy_intp is compatible to Py_Ssize_t */
return PySequence_Repeat(m1, repeat);
}
if (!PyArray_IsScalar(m2, Generic) &&
((Py_TYPE(m2)->tp_as_sequence != NULL) &&
(Py_TYPE(m2)->tp_as_sequence->sq_repeat != NULL)) &&
((Py_TYPE(m2)->tp_as_number == NULL) ||
(Py_TYPE(m2)->tp_as_number->nb_multiply == NULL))) {
/* Try to convert m1 to an int and try sequence repeat */
repeat = PyArray_PyIntAsIntp(m1);
if (error_converting(repeat)) {
return NULL;
}
return PySequence_Repeat(m2, repeat);
}
/* 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 *
voidtype_repr(PyObject *self)
{
PyVoidScalarObject *s = (PyVoidScalarObject*) self;
if (PyDataType_HASFIELDS(s->descr)) {
static PyObject *reprfunc = NULL;
npy_cache_import("numpy.core.arrayprint",
"_void_scalar_repr", &reprfunc);
if (reprfunc == NULL) {
return NULL;
}
return PyObject_CallFunction(reprfunc, "O", 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)) {
static PyObject *reprfunc = NULL;
npy_cache_import("numpy.core.arrayprint",
"_void_scalar_repr", &reprfunc);
if (reprfunc == NULL) {
return NULL;
}
return PyObject_CallFunction(reprfunc, "O", 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__(|type) return 0-dim array";
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 PyObject *
gentype_squeeze(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, "")) {
return NULL;
}
Py_INCREF(self);
return self;
}
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#
*/
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;
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
#endif
if (PyObject_AsReadBuffer(self, (const void **)&buffer, &buflen)<0) {
Py_DECREF(ret);
return NULL;
}
mod = PyImport_ImportModule("numpy.core.multiarray");
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, 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 int
gentype_getbuffer(PyObject *self, Py_buffer *view, int flags)
{
Py_ssize_t len;
void *buf;
/* FIXME: XXX: the format is not implemented! -- this needs more work */
len = gentype_getreadbuf(self, 0, &buf);
return PyBuffer_FillInfo(view, self, buf, len, 1, flags);
}
/* releasebuffer is not needed */
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 cannot be 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_SIZE2 "16"
#define _THIS_SIZE1 "32"
#elif NPY_BITSOF_@CNAME@ == 32
#define _THIS_SIZE2 "32"
#define _THIS_SIZE1 "64"
#elif NPY_BITSOF_@CNAME@ == 64
#define _THIS_SIZE2 "64"
#define _THIS_SIZE1 "128"
#elif NPY_BITSOF_@CNAME@ == 80
#define _THIS_SIZE2 "80"
#define _THIS_SIZE1 "160"
#elif NPY_BITSOF_@CNAME@ == 96
#define _THIS_SIZE2 "96"
#define _THIS_SIZE1 "192"
#elif NPY_BITSOF_@CNAME@ == 128
#define _THIS_SIZE2 "128"
#define _THIS_SIZE1 "256"
#elif NPY_BITSOF_@CNAME@ == 256
#define _THIS_SIZE2 "256"
#define _THIS_SIZE1 "512"
#endif
#define _THIS_DOC "Composed of two " _THIS_SIZE2 " bit floats"
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_SIZE1, /* 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*/
_THIS_DOC, /* 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_SIZE1
#undef _THIS_SIZE2
#undef _THIS_DOC
/**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
float_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, flags);
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 = &float_print;
PyCDoubleArrType_Type.tp_print = &float_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;
}