tmp
/
pip-install-ghxuqwgs
/numpy_78e94bf2b6094bf9a1f3d92042f9bf46
/numpy
/core
/src
/scalarmathmodule.c.src
/* -*- c -*- */ | |
/* The purpose of this module is to add faster math for array scalars | |
that does not go through the ufunc machinery | |
but still supports error-modes. | |
*/ | |
/* Basic operations: | |
* | |
* BINARY: | |
* | |
* add, subtract, multiply, divide, remainder, divmod, power, | |
* floor_divide, true_divide | |
* | |
* lshift, rshift, and, or, xor (integers only) | |
* | |
* UNARY: | |
* | |
* negative, positive, absolute, nonzero, invert, int, long, float, oct, hex | |
* | |
*/ | |
/**begin repeat | |
* #name = byte, short, int, long, longlong# | |
* #type = npy_byte, npy_short, npy_int, npy_long, npy_longlong# | |
*/ | |
static void | |
@name@_ctype_add(@type@ a, @type@ b, @type@ *out) { | |
*out = a + b; | |
if ((*out^a) >= 0 || (*out^b) >= 0) { | |
return; | |
} | |
npy_set_floatstatus_overflow(); | |
return; | |
} | |
static void | |
@name@_ctype_subtract(@type@ a, @type@ b, @type@ *out) { | |
*out = a - b; | |
if ((*out^a) >= 0 || (*out^~b) >= 0) { | |
return; | |
} | |
npy_set_floatstatus_overflow(); | |
return; | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* #name = ubyte, ushort, uint, ulong, ulonglong# | |
* #type = npy_ubyte, npy_ushort, npy_uint, npy_ulong, npy_ulonglong# | |
*/ | |
static void | |
@name@_ctype_add(@type@ a, @type@ b, @type@ *out) { | |
*out = a + b; | |
if (*out >= a && *out >= b) { | |
return; | |
} | |
npy_set_floatstatus_overflow(); | |
return; | |
} | |
static void | |
@name@_ctype_subtract(@type@ a, @type@ b, @type@ *out) { | |
*out = a - b; | |
if (a >= b) { | |
return; | |
} | |
npy_set_floatstatus_overflow(); | |
return; | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* | |
* #name = byte, ubyte, short, ushort, | |
* int, uint, long, ulong# | |
* #type = npy_byte, npy_ubyte, npy_short, npy_ushort, | |
* npy_int, npy_uint, npy_long, npy_ulong# | |
* #big = npy_int, npy_uint, npy_int, npy_uint, | |
* npy_longlong, npy_ulonglong, npy_longlong, npy_ulonglong# | |
* #NAME = BYTE, UBYTE, SHORT, USHORT, | |
* INT, UINT, LONG, ULONG# | |
* #SIZENAME = BYTE*2, SHORT*2, INT*2, LONG*2# | |
* #SIZE = INT*4,LONGLONG*4# | |
* #neg = (1,0)*4# | |
*/ | |
static void | |
@name@_ctype_multiply(@type@ a, @type@ b, @type@ *out) { | |
@big@ temp; | |
temp = ((@big@) a) * ((@big@) b); | |
*out = (@type@) temp; | |
if (temp > NPY_MAX_@NAME@ || temp < NPY_MIN_@NAME@) | |
if (temp > NPY_MAX_@NAME@) | |
npy_set_floatstatus_overflow(); | |
return; | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* | |
* #name = int, uint, long, ulong, | |
* longlong, ulonglong# | |
* #type = npy_int, npy_uint, npy_long, npy_ulong, | |
* npy_longlong, npy_ulonglong# | |
* #SIZE = INT*2, LONG*2, LONGLONG*2# | |
*/ | |
static void | |
@name@_ctype_multiply(@type@ a, @type@ b, @type@ *out) { | |
if (npy_mul_with_overflow_@name@(out, a, b)) { | |
npy_set_floatstatus_overflow(); | |
} | |
return; | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* | |
* #name = byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong# | |
* #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong# | |
* #neg = (1,0)*5# | |
*/ | |
static void | |
@name@_ctype_divide(@type@ a, @type@ b, @type@ *out) { | |
if (b == 0) { | |
npy_set_floatstatus_divbyzero(); | |
*out = 0; | |
} | |
else if (b == -1 && a < 0 && a == -a) { | |
npy_set_floatstatus_overflow(); | |
*out = a / b; | |
} | |
else { | |
@type@ tmp; | |
tmp = a / b; | |
if (((a > 0) != (b > 0)) && (a % b != 0)) { | |
tmp--; | |
} | |
*out = tmp; | |
*out = a / b; | |
} | |
} | |
static void | |
@name@_ctype_remainder(@type@ a, @type@ b, @type@ *out) { | |
if (a == 0 || b == 0) { | |
if (b == 0) npy_set_floatstatus_divbyzero(); | |
*out = 0; | |
return; | |
} | |
else if ((a > 0) == (b > 0)) { | |
*out = a % b; | |
} | |
else { | |
/* handled like Python does */ | |
*out = a % b; | |
if (*out) *out += b; | |
} | |
*out = a % b; | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* | |
* #name = byte, ubyte, short, ushort, int, uint, long, | |
* ulong, longlong, ulonglong# | |
* #otyp = npy_float*4, npy_double*6# | |
*/ | |
/**end repeat**/ | |
/* b will always be positive in this call */ | |
/**begin repeat | |
* | |
* #name = byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong# | |
* #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong# | |
* #upc = BYTE, UBYTE, SHORT, USHORT, INT, UINT, | |
* LONG, ULONG, LONGLONG, ULONGLONG# | |
*/ | |
static void | |
@name@_ctype_power(@type@ a, @type@ b, @type@ *out) { | |
@type@ temp, ix, mult; | |
/* code from Python's intobject.c, with overflow checking removed. */ | |
temp = a; | |
ix = 1; | |
while (b > 0) { | |
if (b & 1) { | |
@name@_ctype_multiply(ix, temp, &mult); | |
ix = mult; | |
if (temp == 0) { | |
break; | |
} | |
} | |
b >>= 1; /* Shift exponent down by 1 bit */ | |
if (b==0) { | |
break; | |
} | |
/* Square the value of temp */ | |
@name@_ctype_multiply(temp, temp, &mult); | |
temp = mult; | |
} | |
*out = ix; | |
} | |
/**end repeat**/ | |
/* QUESTION: Should we check for overflow / underflow in (l,r)shift? */ | |
/**begin repeat | |
* #name = byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong# | |
* #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong# | |
*/ | |
/**begin repeat1 | |
* #oper = and, xor, or, lshift, rshift# | |
* #op = &, ^, |, <<, >># | |
*/ | |
/**end repeat1**/ | |
/**end repeat**/ | |
/**begin repeat | |
* #name = float, double, longdouble# | |
* #type = npy_float, npy_double, npy_longdouble# | |
*/ | |
static @type@ (*_basic_@name@_floor)(@type@); | |
static @type@ (*_basic_@name@_sqrt)(@type@); | |
static @type@ (*_basic_@name@_fmod)(@type@, @type@); | |
/**end repeat**/ | |
static npy_half (*_basic_half_floor)(npy_half); | |
static npy_half (*_basic_half_sqrt)(npy_half); | |
static npy_half (*_basic_half_fmod)(npy_half, npy_half); | |
/**begin repeat | |
* #name = cfloat, cdouble, clongdouble# | |
* #rname = float, double, longdouble# | |
* #rtype = npy_float, npy_double, npy_longdouble# | |
* #c = f,,l# | |
*/ | |
/* Note: complex division by zero must yield some complex inf */ | |
/**end repeat**/ | |
/**begin repeat | |
* #name = float, double, longdouble# | |
* #type = npy_float, npy_double, npy_longdouble# | |
*/ | |
static void | |
@name@_ctype_remainder(@type@ a, @type@ b, @type@ *out) { | |
@type@ mod; | |
mod = _basic_@name@_fmod(a, b); | |
if (mod && (((b < 0) != (mod < 0)))) { | |
mod += b; | |
} | |
*out = mod; | |
} | |
/**end repeat**/ | |
static void | |
half_ctype_remainder(npy_half a, npy_half b, npy_half *out) { | |
float mod, fa = npy_half_to_float(a), fb = npy_half_to_float(b); | |
mod = _basic_float_fmod(fa, fb); | |
if (mod && (((fb < 0) != (mod < 0)))) { | |
mod += fb; | |
} | |
*out = npy_float_to_half(mod); | |
} | |
/**begin repeat | |
* #name = byte, ubyte, short, ushort, int, uint, long, ulong, | |
* longlong, ulonglong, half, float, double, longdouble, | |
* cfloat, cdouble, clongdouble# | |
*/ | |
/**end repeat**/ | |
/**begin repeat | |
* #name = float, double, longdouble# | |
* #type = npy_float, npy_double, npy_longdouble# | |
*/ | |
static npy_@name@ (*_basic_@name@_pow)(@type@ a, @type@ b); | |
static void | |
@name@_ctype_power(@type@ a, @type@ b, @type@ *out) | |
{ | |
*out = _basic_@name@_pow(a, b); | |
} | |
/**end repeat**/ | |
static void | |
half_ctype_power(npy_half a, npy_half b, npy_half *out) | |
{ | |
const npy_float af = npy_half_to_float(a); | |
const npy_float bf = npy_half_to_float(b); | |
const npy_float outf = _basic_float_pow(af,bf); | |
*out = npy_float_to_half(outf); | |
} | |
/**begin repeat | |
* #name = byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong, | |
* float, double, longdouble# | |
* #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong, | |
* npy_float, npy_double, npy_longdouble# | |
* #uns = (0,1)*5,0*3# | |
*/ | |
static void | |
@name@_ctype_negative(@type@ a, @type@ *out) | |
{ | |
npy_set_floatstatus_overflow(); | |
*out = -a; | |
} | |
/**end repeat**/ | |
static void | |
half_ctype_negative(npy_half a, npy_half *out) | |
{ | |
*out = a^0x8000u; | |
} | |
/**begin repeat | |
* #name = cfloat, cdouble, clongdouble# | |
* #type = npy_cfloat, npy_cdouble, npy_clongdouble# | |
*/ | |
static void | |
@name@_ctype_negative(@type@ a, @type@ *out) | |
{ | |
out->real = -a.real; | |
out->imag = -a.imag; | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* #name = byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong, | |
* half, float, double, longdouble# | |
* #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong, | |
* npy_half, npy_float, npy_double, npy_longdouble# | |
*/ | |
static void | |
@name@_ctype_positive(@type@ a, @type@ *out) | |
{ | |
*out = a; | |
} | |
/**end repeat**/ | |
/* | |
* Get the nc_powf, nc_pow, and nc_powl functions from | |
* the data area of the power ufunc in umathmodule. | |
*/ | |
/**begin repeat | |
* #name = cfloat, cdouble, clongdouble# | |
* #type = npy_cfloat, npy_cdouble, npy_clongdouble# | |
*/ | |
static void | |
@name@_ctype_positive(@type@ a, @type@ *out) | |
{ | |
out->real = a.real; | |
out->imag = a.imag; | |
} | |
static void (*_basic_@name@_pow)(@type@ *, @type@ *, @type@ *); | |
static void | |
@name@_ctype_power(@type@ a, @type@ b, @type@ *out) | |
{ | |
_basic_@name@_pow(&a, &b, out); | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* #name = ubyte, ushort, uint, ulong, ulonglong# | |
*/ | |
/**end repeat**/ | |
/**begin repeat | |
* #name = byte, short, int, long, longlong, | |
* float, double, longdouble# | |
* #type = npy_byte, npy_short, npy_int, npy_long, npy_longlong, | |
* npy_float, npy_double, npy_longdouble# | |
*/ | |
static void | |
@name@_ctype_absolute(@type@ a, @type@ *out) | |
{ | |
*out = (a < 0 ? -a : a); | |
} | |
/**end repeat**/ | |
static void | |
half_ctype_absolute(npy_half a, npy_half *out) | |
{ | |
*out = a&0x7fffu; | |
} | |
/**begin repeat | |
* #name = cfloat, cdouble, clongdouble# | |
* #type = npy_cfloat, npy_cdouble, npy_clongdouble# | |
* #rname = float, double, longdouble# | |
* #rtype = npy_float, npy_double, npy_longdouble# | |
*/ | |
static void | |
@name@_ctype_absolute(@type@ a, @rtype@ *out) | |
{ | |
*out = _basic_@rname@_sqrt(a.real*a.real + a.imag*a.imag); | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* #name = byte, ubyte, short, ushort, int, uint, long, | |
* ulong, longlong, ulonglong# | |
*/ | |
/**end repeat**/ | |
/*** END OF BASIC CODE **/ | |
/* The general strategy for commutative binary operators is to | |
* | |
* 1) Convert the types to the common type if both are scalars (0 return) | |
* 2) If both are not scalars use ufunc machinery (-2 return) | |
* 3) If both are scalars but cannot be cast to the right type | |
* return NotImplmented (-1 return) | |
* | |
* 4) Perform the function on the C-type. | |
* 5) If an error condition occurred, check to see | |
* what the current error-handling is and handle the error. | |
* | |
* 6) Construct and return the output scalar. | |
*/ | |
/**begin repeat | |
* #name = byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong, | |
* half, float, longdouble, | |
* cfloat, cdouble, clongdouble# | |
* #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong, | |
* npy_half, npy_float, npy_longdouble, | |
* npy_cfloat, npy_cdouble, npy_clongdouble# | |
* #Name = Byte, UByte, Short, UShort, Int, UInt, | |
* Long, ULong, LongLong, ULongLong, | |
* Half, Float, LongDouble, | |
* CFloat, CDouble, CLongDouble# | |
* #TYPE = NPY_BYTE, NPY_UBYTE, NPY_SHORT, NPY_USHORT, NPY_INT, NPY_UINT, | |
* NPY_LONG, NPY_ULONG, NPY_LONGLONG, NPY_ULONGLONG, | |
* NPY_HALF, NPY_FLOAT, NPY_LONGDOUBLE, | |
* NPY_CFLOAT, NPY_CDOUBLE, NPY_CLONGDOUBLE# | |
*/ | |
static int | |
_@name@_convert_to_ctype(PyObject *a, @type@ *arg1) | |
{ | |
PyObject *temp; | |
if (PyArray_IsScalar(a, @Name@)) { | |
*arg1 = PyArrayScalar_VAL(a, @Name@); | |
return 0; | |
} | |
else if (PyArray_IsScalar(a, Generic)) { | |
PyArray_Descr *descr1; | |
if (!PyArray_IsScalar(a, Number)) { | |
return -1; | |
} | |
descr1 = PyArray_DescrFromTypeObject((PyObject *)Py_TYPE(a)); | |
if (PyArray_CanCastSafely(descr1->type_num, @TYPE@)) { | |
PyArray_CastScalarDirect(a, descr1, arg1, @TYPE@); | |
Py_DECREF(descr1); | |
return 0; | |
} | |
else { | |
Py_DECREF(descr1); | |
return -1; | |
} | |
} | |
else if (PyArray_GetPriority(a, NPY_PRIORITY) > NPY_PRIORITY) { | |
return -2; | |
} | |
else if ((temp = PyArray_ScalarFromObject(a)) != NULL) { | |
int retval = _@name@_convert_to_ctype(temp, arg1); | |
Py_DECREF(temp); | |
return retval; | |
} | |
return -2; | |
} | |
/**end repeat**/ | |
/* Same as above but added exact checks against known python types for speed */ | |
/**begin repeat | |
* #name = double# | |
* #type = npy_double# | |
* #Name = Double# | |
* #TYPE = NPY_DOUBLE# | |
* #PYCHECKEXACT = PyFloat_CheckExact# | |
* #PYEXTRACTCTYPE = PyFloat_AS_DOUBLE# | |
*/ | |
static int | |
_@name@_convert_to_ctype(PyObject *a, @type@ *arg1) | |
{ | |
PyObject *temp; | |
if (@PYCHECKEXACT@(a)){ | |
*arg1 = @PYEXTRACTCTYPE@(a); | |
return 0; | |
} | |
if (PyArray_IsScalar(a, @Name@)) { | |
*arg1 = PyArrayScalar_VAL(a, @Name@); | |
return 0; | |
} | |
else if (PyArray_IsScalar(a, Generic)) { | |
PyArray_Descr *descr1; | |
if (!PyArray_IsScalar(a, Number)) { | |
return -1; | |
} | |
descr1 = PyArray_DescrFromTypeObject((PyObject *)Py_TYPE(a)); | |
if (PyArray_CanCastSafely(descr1->type_num, @TYPE@)) { | |
PyArray_CastScalarDirect(a, descr1, arg1, @TYPE@); | |
Py_DECREF(descr1); | |
return 0; | |
} | |
else { | |
Py_DECREF(descr1); | |
return -1; | |
} | |
} | |
else if (PyArray_GetPriority(a, NPY_PRIORITY) > NPY_PRIORITY) { | |
return -2; | |
} | |
else if ((temp = PyArray_ScalarFromObject(a)) != NULL) { | |
int retval = _@name@_convert_to_ctype(temp, arg1); | |
Py_DECREF(temp); | |
return retval; | |
} | |
return -2; | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* #name = byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong, | |
* half, float, double, cfloat, cdouble# | |
* #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong, | |
* npy_half, npy_float, npy_double, npy_cfloat, npy_cdouble# | |
*/ | |
static int | |
_@name@_convert2_to_ctypes(PyObject *a, @type@ *arg1, | |
PyObject *b, @type@ *arg2) | |
{ | |
int ret; | |
ret = _@name@_convert_to_ctype(a, arg1); | |
if (ret < 0) { | |
return ret; | |
} | |
ret = _@name@_convert_to_ctype(b, arg2); | |
if (ret < 0) { | |
return ret; | |
} | |
return 0; | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* #name = longdouble, clongdouble# | |
* #type = npy_longdouble, npy_clongdouble# | |
*/ | |
static int | |
_@name@_convert2_to_ctypes(PyObject *a, @type@ *arg1, | |
PyObject *b, @type@ *arg2) | |
{ | |
int ret; | |
ret = _@name@_convert_to_ctype(a, arg1); | |
if (ret < 0) { | |
return ret; | |
} | |
ret = _@name@_convert_to_ctype(b, arg2); | |
if (ret == -2) { | |
ret = -3; | |
} | |
if (ret < 0) { | |
return ret; | |
} | |
return 0; | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* | |
* #name = (byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong)*13, | |
* (half, float, double, longdouble, | |
* cfloat, cdouble, clongdouble)*6, | |
* (half, float, double, longdouble)*2# | |
* #Name = (Byte, UByte, Short, UShort, Int, UInt, | |
* Long, ULong,LongLong,ULongLong)*13, | |
* (Half, Float, Double, LongDouble, | |
* CFloat, CDouble, CLongDouble)*6, | |
* (Half, Float, Double, LongDouble)*2# | |
* #type = (npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong)*13, | |
* (npy_half, npy_float, npy_double, npy_longdouble, | |
* npy_cfloat, npy_cdouble, npy_clongdouble)*6, | |
* (npy_half, npy_float, npy_double, npy_longdouble)*2# | |
* | |
* #oper = add*10, subtract*10, multiply*10, divide*10, remainder*10, | |
* divmod*10, floor_divide*10, lshift*10, rshift*10, and*10, | |
* or*10, xor*10, true_divide*10, | |
* add*7, subtract*7, multiply*7, divide*7, floor_divide*7, true_divide*7, | |
* divmod*4, remainder*4# | |
* | |
* #fperr = 1*70,0*50,1*10, | |
* 1*42, | |
* 1*8# | |
* #twoout = 0*50,1*10,0*70, | |
* 0*42, | |
* 1*4,0*4# | |
* #otype = (npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong)*12, | |
* npy_float*4, npy_double*6, | |
* (npy_half, npy_float, npy_double, npy_longdouble, | |
* npy_cfloat, npy_cdouble, npy_clongdouble)*6, | |
* (npy_half, npy_float, npy_double, npy_longdouble)*2# | |
* #OName = (Byte, UByte, Short, UShort, Int, UInt, | |
* Long, ULong, LongLong, ULongLong)*12, | |
* Float*4, Double*6, | |
* (Half, Float, Double, LongDouble, | |
* CFloat, CDouble, CLongDouble)*6, | |
* (Half, Float, Double, LongDouble)*2# | |
*/ | |
static PyObject * | |
@name@_@oper@(PyObject *a, PyObject *b) | |
{ | |
PyObject *ret; | |
@type@ arg1, arg2; | |
/* | |
* NOTE: In gcc >= 4.1, the compiler will reorder floating point | |
* operations and floating point error state checks. In | |
* particular, the arithmetic operations were being reordered | |
* so that the errors weren't caught. Declaring this output | |
* variable volatile was the minimal fix for the issue. | |
* (Ticket #1671) | |
*/ | |
volatile @otype@ out; | |
@otype@ out2; | |
PyObject *obj; | |
int retstatus; | |
int first; | |
switch(_@name@_convert2_to_ctypes(a, &arg1, b, &arg2)) { | |
case 0: | |
break; | |
case -1: | |
/* one of them can't be cast safely must be mixed-types*/ | |
return PyArray_Type.tp_as_number->nb_@oper@(a,b); | |
case -2: | |
/* use default handling */ | |
if (PyErr_Occurred()) { | |
return NULL; | |
} | |
return PyGenericArrType_Type.tp_as_number->nb_@oper@(a,b); | |
case -3: | |
/* | |
* special case for longdouble and clongdouble | |
* because they have a recursive getitem in their dtype | |
*/ | |
Py_INCREF(Py_NotImplemented); | |
return Py_NotImplemented; | |
} | |
PyUFunc_clearfperr(); | |
/* | |
* here we do the actual calculation with arg1 and arg2 | |
* as a function call. | |
*/ | |
@name@_ctype_@oper@(arg1, arg2, (@otype@ *)&out, &out2); | |
@name@_ctype_@oper@(arg1, arg2, (@otype@ *)&out); | |
/* Check status flag. If it is set, then look up what to do */ | |
retstatus = PyUFunc_getfperr(); | |
if (retstatus) { | |
int bufsize, errmask; | |
PyObject *errobj; | |
if (PyUFunc_GetPyValues("@name@_scalars", &bufsize, &errmask, | |
&errobj) < 0) { | |
return NULL; | |
} | |
first = 1; | |
if (PyUFunc_handlefperr(errmask, errobj, retstatus, &first)) { | |
Py_XDECREF(errobj); | |
return NULL; | |
} | |
Py_XDECREF(errobj); | |
} | |
ret = PyTuple_New(2); | |
if (ret == NULL) { | |
return NULL; | |
} | |
obj = PyArrayScalar_New(@OName@); | |
if (obj == NULL) { | |
Py_DECREF(ret); | |
return NULL; | |
} | |
PyArrayScalar_ASSIGN(obj, @OName@, out); | |
PyTuple_SET_ITEM(ret, 0, obj); | |
obj = PyArrayScalar_New(@OName@); | |
if (obj == NULL) { | |
Py_DECREF(ret); | |
return NULL; | |
} | |
PyArrayScalar_ASSIGN(obj, @OName@, out2); | |
PyTuple_SET_ITEM(ret, 1, obj); | |
ret = PyArrayScalar_New(@OName@); | |
if (ret == NULL) { | |
return NULL; | |
} | |
PyArrayScalar_ASSIGN(ret, @OName@, out); | |
return ret; | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* | |
* #name = byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong, | |
* half, float, double, longdouble, | |
* cfloat, cdouble, clongdouble# | |
* | |
* #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong, | |
* npy_half, npy_float, npy_double, npy_longdouble, | |
* npy_cfloat, npy_cdouble, npy_clongdouble# | |
* | |
* #Name = Byte, UByte, Short, UShort, Int, UInt, | |
* Long, ULong, LongLong, ULongLong, | |
* Half, Float, Double, LongDouble, | |
* CFloat, CDouble, CLongDouble# | |
* | |
* #otype = npy_float*4, npy_double*6, npy_half, npy_float, | |
* npy_double, npy_longdouble, | |
* npy_cfloat, npy_cdouble, npy_clongdouble# | |
* | |
* #OName = Float*4, Double*6, Half, Float, | |
* Double, LongDouble, | |
* CFloat, CDouble, CLongDouble# | |
* | |
* #isint = (1,0)*5,0*7# | |
* #cmplx = 0*14,1*3# | |
* #iszero = _IS_ZERO*10, npy_half_iszero, _IS_ZERO*6# | |
* #zero = 0*10, NPY_HALF_ZERO, 0*6# | |
* #one = 1*10, NPY_HALF_ONE, 1*6# | |
*/ | |
static PyObject * | |
@name@_power(PyObject *a, PyObject *b, PyObject *NPY_UNUSED(c)) | |
{ | |
PyObject *ret; | |
@type@ arg1, arg2; | |
int retstatus; | |
int first; | |
@type@ out = {@zero@, @zero@}; | |
switch(_@name@_convert2_to_ctypes(a, &arg1, b, &arg2)) { | |
case 0: | |
break; | |
case -1: | |
/* can't cast both safely mixed-types? */ | |
return PyArray_Type.tp_as_number->nb_power(a,b,NULL); | |
case -2: | |
/* use default handling */ | |
if (PyErr_Occurred()) { | |
return NULL; | |
} | |
return PyGenericArrType_Type.tp_as_number->nb_power(a,b,NULL); | |
case -3: | |
/* | |
* special case for longdouble and clongdouble | |
* because they have a recursive getitem in their dtype | |
*/ | |
Py_INCREF(Py_NotImplemented); | |
return Py_NotImplemented; | |
} | |
PyUFunc_clearfperr(); | |
/* | |
* here we do the actual calculation with arg1 and arg2 | |
* as a function call. | |
*/ | |
if (@iszero@(arg2.real) && @iszero@(arg2.imag)) { | |
out.real = @one@; | |
out.imag = @zero@; | |
} | |
else { | |
@name@_ctype_power(arg1, arg2, &out); | |
} | |
/* Check status flag. If it is set, then look up what to do */ | |
retstatus = PyUFunc_getfperr(); | |
if (retstatus) { | |
int bufsize, errmask; | |
PyObject *errobj; | |
if (PyUFunc_GetPyValues("@name@_scalars", &bufsize, &errmask, | |
&errobj) < 0) { | |
return NULL; | |
} | |
first = 1; | |
if (PyUFunc_handlefperr(errmask, errobj, retstatus, &first)) { | |
Py_XDECREF(errobj); | |
return NULL; | |
} | |
Py_XDECREF(errobj); | |
} | |
ret = PyArrayScalar_New(@Name@); | |
if (ret == NULL) { | |
return NULL; | |
} | |
PyArrayScalar_ASSIGN(ret, @Name@, out); | |
return ret; | |
} | |
static PyObject * | |
@name@_power(PyObject *a, PyObject *b, PyObject *NPY_UNUSED(c)) | |
{ | |
PyObject *ret; | |
@type@ arg1, arg2; | |
int retstatus; | |
int first; | |
@type@ out = @zero@; | |
@otype@ out1 = @zero@; | |
switch(_@name@_convert2_to_ctypes(a, &arg1, b, &arg2)) { | |
case 0: | |
break; | |
case -1: | |
/* can't cast both safely mixed-types? */ | |
return PyArray_Type.tp_as_number->nb_power(a,b,NULL); | |
case -2: | |
/* use default handling */ | |
if (PyErr_Occurred()) { | |
return NULL; | |
} | |
return PyGenericArrType_Type.tp_as_number->nb_power(a,b,NULL); | |
case -3: | |
/* | |
* special case for longdouble and clongdouble | |
* because they have a recursive getitem in their dtype | |
*/ | |
Py_INCREF(Py_NotImplemented); | |
return Py_NotImplemented; | |
} | |
PyUFunc_clearfperr(); | |
/* | |
* here we do the actual calculation with arg1 and arg2 | |
* as a function call. | |
*/ | |
if (@iszero@(arg2)) { | |
out1 = out = @one@; | |
} | |
else if (arg2 < 0) { | |
@name@_ctype_power(arg1, -arg2, &out); | |
out1 = (@otype@) (1.0 / out); | |
} | |
else { | |
@name@_ctype_power(arg1, arg2, &out); | |
} | |
/* Check status flag. If it is set, then look up what to do */ | |
retstatus = PyUFunc_getfperr(); | |
if (retstatus) { | |
int bufsize, errmask; | |
PyObject *errobj; | |
if (PyUFunc_GetPyValues("@name@_scalars", &bufsize, &errmask, | |
&errobj) < 0) { | |
return NULL; | |
} | |
first = 1; | |
if (PyUFunc_handlefperr(errmask, errobj, retstatus, &first)) { | |
Py_XDECREF(errobj); | |
return NULL; | |
} | |
Py_XDECREF(errobj); | |
} | |
if (arg2 < 0) { | |
ret = PyArrayScalar_New(@OName@); | |
if (ret == NULL) { | |
return NULL; | |
} | |
PyArrayScalar_ASSIGN(ret, @OName@, out1); | |
} | |
else { | |
ret = PyArrayScalar_New(@Name@); | |
if (ret == NULL) { | |
return NULL; | |
} | |
PyArrayScalar_ASSIGN(ret, @Name@, out); | |
} | |
return ret; | |
} | |
static PyObject * | |
@name@_power(PyObject *a, PyObject *b, PyObject *NPY_UNUSED(c)) | |
{ | |
PyObject *ret; | |
@type@ arg1, arg2; | |
int retstatus; | |
int first; | |
@type@ out = @zero@; | |
switch(_@name@_convert2_to_ctypes(a, &arg1, b, &arg2)) { | |
case 0: | |
break; | |
case -1: | |
/* can't cast both safely mixed-types? */ | |
return PyArray_Type.tp_as_number->nb_power(a,b,NULL); | |
case -2: | |
/* use default handling */ | |
if (PyErr_Occurred()) { | |
return NULL; | |
} | |
return PyGenericArrType_Type.tp_as_number->nb_power(a,b,NULL); | |
case -3: | |
/* | |
* special case for longdouble and clongdouble | |
* because they have a recursive getitem in their dtype | |
*/ | |
Py_INCREF(Py_NotImplemented); | |
return Py_NotImplemented; | |
} | |
PyUFunc_clearfperr(); | |
/* | |
* here we do the actual calculation with arg1 and arg2 | |
* as a function call. | |
*/ | |
if (@iszero@(arg2)) { | |
out = @one@; | |
} | |
else { | |
@name@_ctype_power(arg1, arg2, &out); | |
} | |
/* Check status flag. If it is set, then look up what to do */ | |
retstatus = PyUFunc_getfperr(); | |
if (retstatus) { | |
int bufsize, errmask; | |
PyObject *errobj; | |
if (PyUFunc_GetPyValues("@name@_scalars", &bufsize, &errmask, | |
&errobj) < 0) { | |
return NULL; | |
} | |
first = 1; | |
if (PyUFunc_handlefperr(errmask, errobj, retstatus, &first)) { | |
Py_XDECREF(errobj); | |
return NULL; | |
} | |
Py_XDECREF(errobj); | |
} | |
ret = PyArrayScalar_New(@Name@); | |
if (ret == NULL) { | |
return NULL; | |
} | |
PyArrayScalar_ASSIGN(ret, @Name@, out); | |
return ret; | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* | |
* #name = cfloat, cdouble, clongdouble# | |
* | |
*/ | |
/**begin repeat1 | |
* | |
* #oper = divmod, remainder# | |
* | |
*/ | |
/**end repeat1**/ | |
/**end repeat**/ | |
/**begin repeat | |
* | |
* #name = half, float, double, longdouble, cfloat, cdouble, clongdouble# | |
* | |
*/ | |
/**begin repeat1 | |
* | |
* #oper = lshift, rshift, and, or, xor# | |
* | |
*/ | |
/**end repeat1**/ | |
/**end repeat**/ | |
/**begin repeat | |
* #name = (byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong, | |
* half, float, double, longdouble, | |
* cfloat, cdouble, clongdouble)*3, | |
* | |
* byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong# | |
* | |
* #type = (npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong, | |
* npy_half, npy_float, npy_double, npy_longdouble, | |
* npy_cfloat, npy_cdouble, npy_clongdouble)*3, | |
* | |
* npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong# | |
* | |
* #otype = (npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong, | |
* npy_half, npy_float, npy_double, npy_longdouble, | |
* npy_cfloat, npy_cdouble, npy_clongdouble)*2, | |
* npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong, | |
* npy_half, npy_float, npy_double, npy_longdouble, | |
* npy_float, npy_double, npy_longdouble, | |
* | |
* npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, | |
* npy_long, npy_ulong, npy_longlong, npy_ulonglong# | |
* | |
* #OName = (Byte, UByte, Short, UShort, Int, UInt, | |
* Long, ULong, LongLong, ULongLong, | |
* Half, Float, Double, LongDouble, | |
* CFloat, CDouble, CLongDouble)*2, | |
* Byte, UByte, Short, UShort, Int, UInt, | |
* Long, ULong, LongLong, ULongLong, | |
* Half, Float, Double, LongDouble, | |
* Float, Double, LongDouble, | |
* | |
* Byte, UByte, Short, UShort, Int, UInt, | |
* Long, ULong, LongLong, ULongLong# | |
* | |
* #oper = negative*17, positive*17, absolute*17, invert*10# | |
*/ | |
static PyObject * | |
@name@_@oper@(PyObject *a) | |
{ | |
@type@ arg1; | |
@otype@ out; | |
PyObject *ret; | |
switch(_@name@_convert_to_ctype(a, &arg1)) { | |
case 0: | |
break; | |
case -1: | |
/* can't cast both safely use different add function */ | |
Py_INCREF(Py_NotImplemented); | |
return Py_NotImplemented; | |
case -2: | |
/* use default handling */ | |
if (PyErr_Occurred()) { | |
return NULL; | |
} | |
return PyGenericArrType_Type.tp_as_number->nb_@oper@(a); | |
} | |
/* | |
* here we do the actual calculation with arg1 and arg2 | |
* make it a function call. | |
*/ | |
@name@_ctype_@oper@(arg1, &out); | |
ret = PyArrayScalar_New(@OName@); | |
PyArrayScalar_ASSIGN(ret, @OName@, out); | |
return ret; | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* | |
* #name = half, float, double, longdouble, cfloat, cdouble, clongdouble# | |
*/ | |
/**end repeat**/ | |
/**begin repeat | |
* | |
* #name = byte, ubyte, short, ushort, int, | |
* uint, long, ulong, longlong, ulonglong, | |
* half, float, double, longdouble, | |
* cfloat, cdouble, clongdouble# | |
* #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, | |
* npy_uint, npy_long, npy_ulong, npy_longlong, npy_ulonglong, | |
* npy_half, npy_float, npy_double, npy_longdouble, | |
* npy_cfloat, npy_cdouble, npy_clongdouble# | |
* #simp = 1*14, 0*3# | |
* #nonzero = _IS_NONZERO*10, !npy_half_iszero, _IS_NONZERO*6# | |
*/ | |
static int | |
NONZERO_NAME(@name@_)(PyObject *a) | |
{ | |
int ret; | |
@type@ arg1; | |
if (_@name@_convert_to_ctype(a, &arg1) < 0) { | |
if (PyErr_Occurred()) { | |
return -1; | |
} | |
return PyGenericArrType_Type.tp_as_number->NONZERO_NAME(nb_)(a); | |
} | |
/* | |
* here we do the actual calculation with arg1 and arg2 | |
* make it a function call. | |
*/ | |
ret = @nonzero@(arg1); | |
ret = (@nonzero@(arg1.real) || @nonzero@(arg1.imag)); | |
return ret; | |
} | |
/**end repeat**/ | |
static int | |
emit_complexwarning(void) | |
{ | |
static PyObject *cls = NULL; | |
if (cls == NULL) { | |
PyObject *mod; | |
mod = PyImport_ImportModule("numpy.core"); | |
assert(mod != NULL); | |
cls = PyObject_GetAttrString(mod, "ComplexWarning"); | |
assert(cls != NULL); | |
Py_DECREF(mod); | |
} | |
return PyErr_WarnEx(cls, | |
"Casting complex values to real discards the imaginary part", 1); | |
} | |
/**begin repeat | |
* | |
* #name = byte, ubyte, short, ushort, int, | |
* uint, long, ulong, longlong, ulonglong, | |
* half, float, double, longdouble, | |
* cfloat, cdouble, clongdouble# | |
* | |
* #Name = Byte, UByte, Short, UShort, Int, | |
* UInt, Long, ULong, LongLong, ULongLong, | |
* Half, Float, Double, LongDouble, | |
* CFloat, CDouble, CLongDouble# | |
* | |
* #cmplx = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1# | |
* #sign = (signed, unsigned)*5, , , , , , , # | |
* #unsigntyp = 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0*7# | |
* #ctype = long*8, PY_LONG_LONG*2, double*7# | |
* #to_ctype = , , , , , , , , , , npy_half_to_double, , , , , , # | |
* #realtyp = 0*10, 1*7# | |
* #func = (PyLong_FromLong, PyLong_FromUnsignedLong)*4, | |
* PyLong_FromLongLong, PyLong_FromUnsignedLongLong, | |
* PyLong_FromDouble*7# | |
*/ | |
static PyObject * | |
@name@_int(PyObject *obj) | |
{ | |
@sign@ @ctype@ x= @to_ctype@(PyArrayScalar_VAL(obj, @Name@).real); | |
int ret; | |
@sign@ @ctype@ x= @to_ctype@(PyArrayScalar_VAL(obj, @Name@)); | |
double ix; | |
modf(x, &ix); | |
x = ix; | |
ret = emit_complexwarning(); | |
if (ret < 0) { | |
return NULL; | |
} | |
if(x < LONG_MAX) | |
return PyInt_FromLong(x); | |
if(LONG_MIN < x && x < LONG_MAX) | |
return PyInt_FromLong(x); | |
return @func@(x); | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* | |
* #name = (byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong, | |
* half, float, double, longdouble, | |
* cfloat, cdouble, clongdouble)*2# | |
* #Name = (Byte, UByte, Short, UShort, Int, UInt, | |
* Long, ULong, LongLong, ULongLong, | |
* Half, Float, Double, LongDouble, | |
* CFloat, CDouble, CLongDouble)*2# | |
* #cmplx = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1)*2# | |
* #to_ctype = (, , , , , , , , , , npy_half_to_double, , , , , , )*2# | |
* #which = long*17, float*17# | |
* #func = (PyLong_FromLongLong, PyLong_FromUnsignedLongLong)*5, | |
* PyLong_FromDouble*7, PyFloat_FromDouble*17# | |
*/ | |
static PyObject * | |
@name@_@which@(PyObject *obj) | |
{ | |
int ret; | |
ret = emit_complexwarning(); | |
if (ret < 0) { | |
return NULL; | |
} | |
return @func@(@to_ctype@((PyArrayScalar_VAL(obj, @Name@)).real)); | |
return @func@(@to_ctype@(PyArrayScalar_VAL(obj, @Name@))); | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* | |
* #name = (byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong, | |
* half, float, double, longdouble, | |
* cfloat, cdouble, clongdouble)*2# | |
* #oper = oct*17, hex*17# | |
* #kind = (int*5, long*5, int*2, long*2, int, long*2)*2# | |
* #cap = (Int*5, Long*5, Int*2, Long*2, Int, Long*2)*2# | |
*/ | |
static PyObject * | |
@name@_@oper@(PyObject *obj) | |
{ | |
PyObject *pyint; | |
pyint = @name@_@kind@(obj); | |
if (pyint == NULL) { | |
return NULL; | |
} | |
return Py@cap@_Type.tp_as_number->nb_@oper@(pyint); | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* #oper = le, ge, lt, gt, eq, ne# | |
* #op = <=, >=, <, >, ==, !=# | |
* #halfop = npy_half_le, npy_half_ge, npy_half_lt, | |
* npy_half_gt, npy_half_eq, npy_half_ne# | |
*/ | |
/**end repeat**/ | |
/**begin repeat | |
* #name = byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong, | |
* half, float, double, longdouble, | |
* cfloat, cdouble, clongdouble# | |
* #simp = def*10, def_half, def*3, cmplx*3# | |
*/ | |
static PyObject* | |
@name@_richcompare(PyObject *self, PyObject *other, int cmp_op) | |
{ | |
npy_@name@ arg1, arg2; | |
int out=0; | |
switch(_@name@_convert2_to_ctypes(self, &arg1, other, &arg2)) { | |
case 0: | |
break; | |
case -1: | |
/* can't cast both safely use different add function */ | |
case -2: | |
/* use ufunc */ | |
if (PyErr_Occurred()) { | |
return NULL; | |
} | |
return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op); | |
case -3: | |
/* | |
* special case for longdouble and clongdouble | |
* because they have a recursive getitem in their dtype | |
*/ | |
Py_INCREF(Py_NotImplemented); | |
return Py_NotImplemented; | |
} | |
/* here we do the actual calculation with arg1 and arg2 */ | |
switch (cmp_op) { | |
case Py_EQ: | |
out = @simp@_cmp_eq(arg1, arg2); | |
break; | |
case Py_NE: | |
out = @simp@_cmp_ne(arg1, arg2); | |
break; | |
case Py_LE: | |
out = @simp@_cmp_le(arg1, arg2); | |
break; | |
case Py_GE: | |
out = @simp@_cmp_ge(arg1, arg2); | |
break; | |
case Py_LT: | |
out = @simp@_cmp_lt(arg1, arg2); | |
break; | |
case Py_GT: | |
out = @simp@_cmp_gt(arg1, arg2); | |
break; | |
} | |
if (out) { | |
PyArrayScalar_RETURN_TRUE; | |
} | |
else { | |
PyArrayScalar_RETURN_FALSE; | |
} | |
} | |
/**end repeat**/ | |
/**begin repeat | |
* #name = byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong, | |
* half, float, double, longdouble, | |
* cfloat, cdouble, clongdouble# | |
**/ | |
static PyNumberMethods @name@_as_number = { | |
(binaryfunc)@name@_add, /*nb_add*/ | |
(binaryfunc)@name@_subtract, /*nb_subtract*/ | |
(binaryfunc)@name@_multiply, /*nb_multiply*/ | |
(binaryfunc)@name@_divide, /*nb_divide*/ | |
(binaryfunc)@name@_remainder, /*nb_remainder*/ | |
(binaryfunc)@name@_divmod, /*nb_divmod*/ | |
(ternaryfunc)@name@_power, /*nb_power*/ | |
(unaryfunc)@name@_negative, | |
(unaryfunc)@name@_positive, /*nb_pos*/ | |
(unaryfunc)@name@_absolute, /*nb_abs*/ | |
(inquiry)@name@_bool, /*nb_bool*/ | |
(inquiry)@name@_nonzero, /*nb_nonzero*/ | |
(unaryfunc)@name@_invert, /*nb_invert*/ | |
(binaryfunc)@name@_lshift, /*nb_lshift*/ | |
(binaryfunc)@name@_rshift, /*nb_rshift*/ | |
(binaryfunc)@name@_and, /*nb_and*/ | |
(binaryfunc)@name@_xor, /*nb_xor*/ | |
(binaryfunc)@name@_or, /*nb_or*/ | |
0, /*nb_coerce*/ | |
(unaryfunc)@name@_int, /*nb_int*/ | |
(unaryfunc)0, /*nb_reserved*/ | |
(unaryfunc)@name@_long, /*nb_long*/ | |
(unaryfunc)@name@_float, /*nb_float*/ | |
(unaryfunc)@name@_oct, /*nb_oct*/ | |
(unaryfunc)@name@_hex, /*nb_hex*/ | |
0, /*inplace_add*/ | |
0, /*inplace_subtract*/ | |
0, /*inplace_multiply*/ | |
0, /*inplace_divide*/ | |
0, /*inplace_remainder*/ | |
0, /*inplace_power*/ | |
0, /*inplace_lshift*/ | |
0, /*inplace_rshift*/ | |
0, /*inplace_and*/ | |
0, /*inplace_xor*/ | |
0, /*inplace_or*/ | |
(binaryfunc)@name@_floor_divide, /*nb_floor_divide*/ | |
(binaryfunc)@name@_true_divide, /*nb_true_divide*/ | |
0, /*nb_inplace_floor_divide*/ | |
0, /*nb_inplace_true_divide*/ | |
(unaryfunc)NULL, /*nb_index*/ | |
}; | |
/**end repeat**/ | |
static void *saved_tables_arrtype[9]; | |
static void | |
add_scalarmath(void) | |
{ | |
/**begin repeat | |
* #name = byte, ubyte, short, ushort, int, uint, | |
* long, ulong, longlong, ulonglong, | |
* half, float, double, longdouble, | |
* cfloat, cdouble, clongdouble# | |
* #NAME = Byte, UByte, Short, UShort, Int, UInt, | |
* Long, ULong, LongLong, ULongLong, | |
* Half, Float, Double, LongDouble, | |
* CFloat, CDouble, CLongDouble# | |
**/ | |
@name@_as_number.nb_index = Py@NAME@ArrType_Type.tp_as_number->nb_index; | |
Py@NAME@ArrType_Type.tp_as_number = &(@name@_as_number); | |
Py@NAME@ArrType_Type.tp_richcompare = @name@_richcompare; | |
/**end repeat**/ | |
saved_tables_arrtype[0] = PyLongArrType_Type.tp_as_number; | |
saved_tables_arrtype[1] = PyLongArrType_Type.tp_compare; | |
saved_tables_arrtype[2] = PyLongArrType_Type.tp_richcompare; | |
saved_tables_arrtype[3] = PyDoubleArrType_Type.tp_as_number; | |
saved_tables_arrtype[4] = PyDoubleArrType_Type.tp_compare; | |
saved_tables_arrtype[5] = PyDoubleArrType_Type.tp_richcompare; | |
saved_tables_arrtype[6] = PyCDoubleArrType_Type.tp_as_number; | |
saved_tables_arrtype[7] = PyCDoubleArrType_Type.tp_compare; | |
saved_tables_arrtype[8] = PyCDoubleArrType_Type.tp_richcompare; | |
} | |
static int | |
get_functions(void) | |
{ | |
PyObject *mm, *obj; | |
void **funcdata; | |
char *signatures; | |
int i, j; | |
int ret = -1; | |
/* Get the nc_pow functions */ | |
/* Get the pow functions */ | |
mm = PyImport_ImportModule("numpy.core.umath"); | |
if (mm == NULL) { | |
return -1; | |
} | |
obj = PyObject_GetAttrString(mm, "power"); | |
if (obj == NULL) { | |
goto fail; | |
} | |
funcdata = ((PyUFuncObject *)obj)->data; | |
signatures = ((PyUFuncObject *)obj)->types; | |
i = 0; | |
j = 0; | |
while (signatures[i] != NPY_FLOAT) { | |
i += 3; | |
j++; | |
} | |
_basic_float_pow = funcdata[j]; | |
_basic_double_pow = funcdata[j + 1]; | |
_basic_longdouble_pow = funcdata[j + 2]; | |
_basic_cfloat_pow = funcdata[j + 3]; | |
_basic_cdouble_pow = funcdata[j + 4]; | |
_basic_clongdouble_pow = funcdata[j + 5]; | |
Py_DECREF(obj); | |
/* Get the floor functions */ | |
obj = PyObject_GetAttrString(mm, "floor"); | |
if (obj == NULL) { | |
goto fail; | |
} | |
funcdata = ((PyUFuncObject *)obj)->data; | |
signatures = ((PyUFuncObject *)obj)->types; | |
i = 0; | |
j = 0; | |
while(signatures[i] != NPY_FLOAT) { | |
i += 2; | |
j++; | |
} | |
_basic_half_floor = funcdata[j - 1]; | |
_basic_float_floor = funcdata[j]; | |
_basic_double_floor = funcdata[j + 1]; | |
_basic_longdouble_floor = funcdata[j + 2]; | |
Py_DECREF(obj); | |
/* Get the sqrt functions */ | |
obj = PyObject_GetAttrString(mm, "sqrt"); | |
if (obj == NULL) { | |
goto fail; | |
} | |
funcdata = ((PyUFuncObject *)obj)->data; | |
signatures = ((PyUFuncObject *)obj)->types; | |
/* | |
* sqrt ufunc is specialized for double and float loops in | |
* generate_umath.py, the first to go into FLOAT/DOUBLE_sqrt | |
* they have the same signature as the scalar variants so we need to skip | |
* over them | |
*/ | |
i = 4; | |
j = 2; | |
while (signatures[i] != NPY_FLOAT) { | |
i += 2; j++; | |
} | |
_basic_half_sqrt = funcdata[j - 1]; | |
_basic_float_sqrt = funcdata[j]; | |
_basic_double_sqrt = funcdata[j + 1]; | |
_basic_longdouble_sqrt = funcdata[j + 2]; | |
Py_DECREF(obj); | |
/* Get the fmod functions */ | |
obj = PyObject_GetAttrString(mm, "fmod"); | |
if (obj == NULL) { | |
goto fail; | |
} | |
funcdata = ((PyUFuncObject *)obj)->data; | |
signatures = ((PyUFuncObject *)obj)->types; | |
i = 0; | |
j = 0; | |
while (signatures[i] != NPY_FLOAT) { | |
i += 3; | |
j++; | |
} | |
_basic_half_fmod = funcdata[j - 1]; | |
_basic_float_fmod = funcdata[j]; | |
_basic_double_fmod = funcdata[j + 1]; | |
_basic_longdouble_fmod = funcdata[j + 2]; | |
Py_DECREF(obj); | |
return ret = 0; | |
fail: | |
Py_DECREF(mm); | |
return ret; | |
} | |
static void *saved_tables[9]; | |
char doc_alterpyscalars[] = ""; | |
static PyObject * | |
alter_pyscalars(PyObject *NPY_UNUSED(dummy), PyObject *args) | |
{ | |
int n; | |
PyObject *obj; | |
n = PyTuple_GET_SIZE(args); | |
while (n--) { | |
obj = PyTuple_GET_ITEM(args, n); | |
if (obj == (PyObject *)(&PyInt_Type)) { | |
PyInt_Type.tp_as_number = PyLongArrType_Type.tp_as_number; | |
PyInt_Type.tp_compare = PyLongArrType_Type.tp_compare; | |
PyInt_Type.tp_richcompare = PyLongArrType_Type.tp_richcompare; | |
} | |
else | |
if (obj == (PyObject *)(&PyFloat_Type)) { | |
PyFloat_Type.tp_as_number = PyDoubleArrType_Type.tp_as_number; | |
PyFloat_Type.tp_compare = PyDoubleArrType_Type.tp_compare; | |
PyFloat_Type.tp_richcompare = PyDoubleArrType_Type.tp_richcompare; | |
} | |
else if (obj == (PyObject *)(&PyComplex_Type)) { | |
PyComplex_Type.tp_as_number = PyCDoubleArrType_Type.tp_as_number; | |
PyComplex_Type.tp_compare = PyCDoubleArrType_Type.tp_compare; | |
PyComplex_Type.tp_richcompare = \ | |
PyCDoubleArrType_Type.tp_richcompare; | |
} | |
else { | |
PyErr_SetString(PyExc_ValueError, | |
"arguments must be int, float, or complex"); | |
return NULL; | |
} | |
} | |
Py_INCREF(Py_None); | |
return Py_None; | |
} | |
char doc_restorepyscalars[] = ""; | |
static PyObject * | |
restore_pyscalars(PyObject *NPY_UNUSED(dummy), PyObject *args) | |
{ | |
int n; | |
PyObject *obj; | |
n = PyTuple_GET_SIZE(args); | |
while (n--) { | |
obj = PyTuple_GET_ITEM(args, n); | |
if (obj == (PyObject *)(&PyInt_Type)) { | |
PyInt_Type.tp_as_number = saved_tables[0]; | |
PyInt_Type.tp_compare = saved_tables[1]; | |
PyInt_Type.tp_richcompare = saved_tables[2]; | |
} | |
else | |
if (obj == (PyObject *)(&PyFloat_Type)) { | |
PyFloat_Type.tp_as_number = saved_tables[3]; | |
PyFloat_Type.tp_compare = saved_tables[4]; | |
PyFloat_Type.tp_richcompare = saved_tables[5]; | |
} | |
else if (obj == (PyObject *)(&PyComplex_Type)) { | |
PyComplex_Type.tp_as_number = saved_tables[6]; | |
PyComplex_Type.tp_compare = saved_tables[7]; | |
PyComplex_Type.tp_richcompare = saved_tables[8]; | |
} | |
else { | |
PyErr_SetString(PyExc_ValueError, | |
"arguments must be int, float, or complex"); | |
return NULL; | |
} | |
} | |
Py_INCREF(Py_None); | |
return Py_None; | |
} | |
char doc_usepythonmath[] = ""; | |
static PyObject * | |
use_pythonmath(PyObject *NPY_UNUSED(dummy), PyObject *args) | |
{ | |
int n; | |
PyObject *obj; | |
n = PyTuple_GET_SIZE(args); | |
while (n--) { | |
obj = PyTuple_GET_ITEM(args, n); | |
if (obj == (PyObject *)(&PyInt_Type)) { | |
PyLongArrType_Type.tp_as_number = saved_tables[0]; | |
PyLongArrType_Type.tp_compare = saved_tables[1]; | |
PyLongArrType_Type.tp_richcompare = saved_tables[2]; | |
} | |
else | |
if (obj == (PyObject *)(&PyFloat_Type)) { | |
PyDoubleArrType_Type.tp_as_number = saved_tables[3]; | |
PyDoubleArrType_Type.tp_compare = saved_tables[4]; | |
PyDoubleArrType_Type.tp_richcompare = saved_tables[5]; | |
} | |
else if (obj == (PyObject *)(&PyComplex_Type)) { | |
PyCDoubleArrType_Type.tp_as_number = saved_tables[6]; | |
PyCDoubleArrType_Type.tp_compare = saved_tables[7]; | |
PyCDoubleArrType_Type.tp_richcompare = saved_tables[8]; | |
} | |
else { | |
PyErr_SetString(PyExc_ValueError, | |
"arguments must be int, float, or complex"); | |
return NULL; | |
} | |
} | |
Py_INCREF(Py_None); | |
return Py_None; | |
} | |
char doc_usescalarmath[] = ""; | |
static PyObject * | |
use_scalarmath(PyObject *NPY_UNUSED(dummy), PyObject *args) | |
{ | |
int n; | |
PyObject *obj; | |
n = PyTuple_GET_SIZE(args); | |
while (n--) { | |
obj = PyTuple_GET_ITEM(args, n); | |
if (obj == (PyObject *)(&PyInt_Type)) { | |
PyLongArrType_Type.tp_as_number = saved_tables_arrtype[0]; | |
PyLongArrType_Type.tp_compare = saved_tables_arrtype[1]; | |
PyLongArrType_Type.tp_richcompare = saved_tables_arrtype[2]; | |
} | |
else | |
if (obj == (PyObject *)(&PyFloat_Type)) { | |
PyDoubleArrType_Type.tp_as_number = saved_tables_arrtype[3]; | |
PyDoubleArrType_Type.tp_compare = saved_tables_arrtype[4]; | |
PyDoubleArrType_Type.tp_richcompare = saved_tables_arrtype[5]; | |
} | |
else if (obj == (PyObject *)(&PyComplex_Type)) { | |
PyCDoubleArrType_Type.tp_as_number = saved_tables_arrtype[6]; | |
PyCDoubleArrType_Type.tp_compare = saved_tables_arrtype[7]; | |
PyCDoubleArrType_Type.tp_richcompare = saved_tables_arrtype[8]; | |
} | |
else { | |
PyErr_SetString(PyExc_ValueError, | |
"arguments must be int, float, or complex"); | |
return NULL; | |
} | |
} | |
Py_INCREF(Py_None); | |
return Py_None; | |
} | |
static struct PyMethodDef methods[] = { | |
{"alter_pythonmath", | |
(PyCFunction) alter_pyscalars, | |
METH_VARARGS, doc_alterpyscalars}, | |
{"restore_pythonmath", | |
(PyCFunction) restore_pyscalars, | |
METH_VARARGS, doc_restorepyscalars}, | |
{"use_pythonmath", | |
(PyCFunction) use_pythonmath, | |
METH_VARARGS, doc_usepythonmath}, | |
{"use_scalarmath", | |
(PyCFunction) use_scalarmath, | |
METH_VARARGS, doc_usescalarmath}, | |
{NULL, NULL, 0, NULL} | |
}; | |
static struct PyModuleDef moduledef = { | |
PyModuleDef_HEAD_INIT, | |
"scalarmath", | |
NULL, | |
-1, | |
methods, | |
NULL, | |
NULL, | |
NULL, | |
NULL | |
}; | |
PyMODINIT_FUNC PyInit_scalarmath(void) | |
PyMODINIT_FUNC | |
initscalarmath(void) | |
{ | |
PyObject *m = PyModule_Create(&moduledef); | |
if (!m) { | |
return NULL; | |
} | |
Py_InitModule("scalarmath", methods); | |
import_array(); | |
import_umath(); | |
if (get_functions() < 0) { | |
return RETVAL; | |
} | |
add_scalarmath(); | |
saved_tables[0] = PyInt_Type.tp_as_number; | |
saved_tables[1] = PyInt_Type.tp_compare; | |
saved_tables[2] = PyInt_Type.tp_richcompare; | |
saved_tables[3] = PyFloat_Type.tp_as_number; | |
saved_tables[4] = PyFloat_Type.tp_compare; | |
saved_tables[5] = PyFloat_Type.tp_richcompare; | |
saved_tables[6] = PyComplex_Type.tp_as_number; | |
saved_tables[7] = PyComplex_Type.tp_compare; | |
saved_tables[8] = PyComplex_Type.tp_richcompare; | |
return RETVAL; | |
} | |