/* -*- 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. */ #define NPY_NO_DEPRECATED_API NPY_API_VERSION #include "Python.h" #include "numpy/arrayobject.h" #include "numpy/ufuncobject.h" #include "numpy/arrayscalars.h" #include "npy_pycompat.h" #include "numpy/halffloat.h" #include "scalarmathmodule.h" /* 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**/ #ifndef NPY_SIZEOF_BYTE #define NPY_SIZEOF_BYTE 1 #endif /**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# */ #if NPY_SIZEOF_@SIZE@ > NPY_SIZEOF_@SIZENAME@ static void @name@_ctype_multiply(@type@ a, @type@ b, @type@ *out) { @big@ temp; temp = ((@big@) a) * ((@big@) b); *out = (@type@) temp; #if @neg@ if (temp > NPY_MAX_@NAME@ || temp < NPY_MIN_@NAME@) #else if (temp > NPY_MAX_@NAME@) #endif npy_set_floatstatus_overflow(); return; } #endif /**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# */ #if NPY_SIZEOF_LONGLONG == NPY_SIZEOF_@SIZE@ 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; } #endif /**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; } #if @neg@ else if (b == -1 && a < 0 && a == -a) { npy_set_floatstatus_overflow(); *out = a / b; } #endif else { #if @neg@ @type@ tmp; tmp = a / b; if (((a > 0) != (b > 0)) && (a % b != 0)) { tmp--; } *out = tmp; #else *out = a / b; #endif } } #define @name@_ctype_floor_divide @name@_ctype_divide 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; } #if @neg@ else if ((a > 0) == (b > 0)) { *out = a % b; } else { /* handled like Python does */ *out = a % b; if (*out) *out += b; } #else *out = a % b; #endif } /**end repeat**/ /**begin repeat * * #name = byte, ubyte, short, ushort, int, uint, long, * ulong, longlong, ulonglong# * #otyp = npy_float*4, npy_double*6# */ #define @name@_ctype_true_divide(a, b, out) \ *(out) = ((@otyp@) (a)) / ((@otyp@) (b)); /**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 = &, ^, |, <<, >># */ #define @name@_ctype_@oper@(arg1, arg2, out) *(out) = (arg1) @op@ (arg2) /**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@); #define @name@_ctype_add(a, b, outp) *(outp) = a + b #define @name@_ctype_subtract(a, b, outp) *(outp) = a - b #define @name@_ctype_multiply(a, b, outp) *(outp) = a * b #define @name@_ctype_divide(a, b, outp) *(outp) = a / b #define @name@_ctype_true_divide @name@_ctype_divide #define @name@_ctype_floor_divide(a, b, outp) \ *(outp) = _basic_@name@_floor((a) / (b)) /**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); #define half_ctype_add(a, b, outp) *(outp) = \ npy_float_to_half(npy_half_to_float(a) + npy_half_to_float(b)) #define half_ctype_subtract(a, b, outp) *(outp) = \ npy_float_to_half(npy_half_to_float(a) - npy_half_to_float(b)) #define half_ctype_multiply(a, b, outp) *(outp) = \ npy_float_to_half(npy_half_to_float(a) * npy_half_to_float(b)) #define half_ctype_divide(a, b, outp) *(outp) = \ npy_float_to_half(npy_half_to_float(a) / npy_half_to_float(b)) #define half_ctype_true_divide half_ctype_divide #define half_ctype_floor_divide(a, b, outp) \ *(outp) = npy_float_to_half(_basic_float_floor(npy_half_to_float(a) / \ npy_half_to_float(b))) /**begin repeat * #name = cfloat, cdouble, clongdouble# * #rname = float, double, longdouble# * #rtype = npy_float, npy_double, npy_longdouble# * #c = f,,l# */ #define @name@_ctype_add(a, b, outp) do{ \ (outp)->real = (a).real + (b).real; \ (outp)->imag = (a).imag + (b).imag; \ } while(0) #define @name@_ctype_subtract(a, b, outp) do{ \ (outp)->real = (a).real - (b).real; \ (outp)->imag = (a).imag - (b).imag; \ } while(0) #define @name@_ctype_multiply(a, b, outp) do{ \ (outp)->real = (a).real * (b).real - (a).imag * (b).imag; \ (outp)->imag = (a).real * (b).imag + (a).imag * (b).real; \ } while(0) /* Note: complex division by zero must yield some complex inf */ #define @name@_ctype_divide(a, b, outp) do{ \ @rtype@ d = (b).real*(b).real + (b).imag*(b).imag; \ if (d != 0) { \ (outp)->real = ((a).real*(b).real + (a).imag*(b).imag)/d; \ (outp)->imag = ((a).imag*(b).real - (a).real*(b).imag)/d; \ } \ else { \ (outp)->real = (a).real/d; \ (outp)->imag = (a).imag/d; \ } \ } while(0) #define @name@_ctype_true_divide @name@_ctype_divide #define @name@_ctype_floor_divide(a, b, outp) do { \ (outp)->real = _basic_@rname@_floor \ (((a).real*(b).real + (a).imag*(b).imag) / \ ((b).real*(b).real + (b).imag*(b).imag)); \ (outp)->imag = 0; \ } while(0) /**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# */ #define @name@_ctype_divmod(a, b, out, out2) { \ @name@_ctype_floor_divide(a, b, out); \ @name@_ctype_remainder(a, b, out2); \ } /**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) { #if @uns@ npy_set_floatstatus_overflow(); #endif *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# */ #define @name@_ctype_absolute @name@_ctype_positive /**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# */ #define @name@_ctype_invert(a, out) *(out) = ~a; /**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**/ #if defined(NPY_PY3K) #define CODEGEN_SKIP_divide_FLAG #endif /**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# */ #if !defined(CODEGEN_SKIP_@oper@_FLAG) 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; #if @twoout@ @otype@ out2; PyObject *obj; #endif #if @fperr@ int retstatus; int first; #endif 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; } #if @fperr@ PyUFunc_clearfperr(); #endif /* * here we do the actual calculation with arg1 and arg2 * as a function call. */ #if @twoout@ @name@_ctype_@oper@(arg1, arg2, (@otype@ *)&out, &out2); #else @name@_ctype_@oper@(arg1, arg2, (@otype@ *)&out); #endif #if @fperr@ /* 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); } #endif #if @twoout@ 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); #else ret = PyArrayScalar_New(@OName@); if (ret == NULL) { return NULL; } PyArrayScalar_ASSIGN(ret, @OName@, out); #endif return ret; } #endif /**end repeat**/ #undef CODEGEN_SKIP_divide_FLAG #define _IS_ZERO(x) (x == 0) /**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# */ #if @cmplx@ 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; } #elif @isint@ 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; } #else 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; } #endif /**end repeat**/ #undef _IS_ZERO /**begin repeat * * #name = cfloat, cdouble, clongdouble# * */ /**begin repeat1 * * #oper = divmod, remainder# * */ #define @name@_@oper@ NULL /**end repeat1**/ /**end repeat**/ /**begin repeat * * #name = half, float, double, longdouble, cfloat, cdouble, clongdouble# * */ /**begin repeat1 * * #oper = lshift, rshift, and, or, xor# * */ #define @name@_@oper@ NULL /**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# */ #define @name@_invert NULL /**end repeat**/ #if defined(NPY_PY3K) #define NONZERO_NAME(prefix) prefix##bool #else #define NONZERO_NAME(prefix) prefix##nonzero #endif #define _IS_NONZERO(x) (x != 0) /**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. */ #if @simp@ ret = @nonzero@(arg1); #else ret = (@nonzero@(arg1.real) || @nonzero@(arg1.imag)); #endif return ret; } /**end repeat**/ #undef _IS_NONZERO 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) { #if @cmplx@ @sign@ @ctype@ x= @to_ctype@(PyArrayScalar_VAL(obj, @Name@).real); int ret; #else @sign@ @ctype@ x= @to_ctype@(PyArrayScalar_VAL(obj, @Name@)); #endif #if @realtyp@ double ix; modf(x, &ix); x = ix; #endif #if @cmplx@ ret = emit_complexwarning(); if (ret < 0) { return NULL; } #endif #if @unsigntyp@ if(x < LONG_MAX) return PyInt_FromLong(x); #else if(LONG_MIN < x && x < LONG_MAX) return PyInt_FromLong(x); #endif 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) { #if @cmplx@ int ret; ret = emit_complexwarning(); if (ret < 0) { return NULL; } return @func@(@to_ctype@((PyArrayScalar_VAL(obj, @Name@)).real)); #else return @func@(@to_ctype@(PyArrayScalar_VAL(obj, @Name@))); #endif } /**end repeat**/ #if !defined(NPY_PY3K) /**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**/ #endif /**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# */ #define def_cmp_@oper@(arg1, arg2) (arg1 @op@ arg2) #define cmplx_cmp_@oper@(arg1, arg2) ((arg1.real == arg2.real) ? \ arg1.imag @op@ arg2.imag : \ arg1.real @op@ arg2.real) #define def_half_cmp_@oper@(arg1, arg2) @halfop@(arg1, arg2) /**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*/ #if defined(NPY_PY3K) #else (binaryfunc)@name@_divide, /*nb_divide*/ #endif (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*/ #if defined(NPY_PY3K) (inquiry)@name@_bool, /*nb_bool*/ #else (inquiry)@name@_nonzero, /*nb_nonzero*/ #endif (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*/ #if defined(NPY_PY3K) #else 0, /*nb_coerce*/ #endif (unaryfunc)@name@_int, /*nb_int*/ #if defined(NPY_PY3K) (unaryfunc)0, /*nb_reserved*/ #else (unaryfunc)@name@_long, /*nb_long*/ #endif (unaryfunc)@name@_float, /*nb_float*/ #if defined(NPY_PY3K) #else (unaryfunc)@name@_oct, /*nb_oct*/ (unaryfunc)@name@_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)@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; #if !defined(NPY_PY3K) saved_tables_arrtype[1] = PyLongArrType_Type.tp_compare; #endif saved_tables_arrtype[2] = PyLongArrType_Type.tp_richcompare; saved_tables_arrtype[3] = PyDoubleArrType_Type.tp_as_number; #if !defined(NPY_PY3K) saved_tables_arrtype[4] = PyDoubleArrType_Type.tp_compare; #endif saved_tables_arrtype[5] = PyDoubleArrType_Type.tp_richcompare; saved_tables_arrtype[6] = PyCDoubleArrType_Type.tp_as_number; #if !defined(NPY_PY3K) saved_tables_arrtype[7] = PyCDoubleArrType_Type.tp_compare; #endif 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 !defined(NPY_PY3K) 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 #endif if (obj == (PyObject *)(&PyFloat_Type)) { PyFloat_Type.tp_as_number = PyDoubleArrType_Type.tp_as_number; #if !defined(NPY_PY3K) PyFloat_Type.tp_compare = PyDoubleArrType_Type.tp_compare; #endif PyFloat_Type.tp_richcompare = PyDoubleArrType_Type.tp_richcompare; } else if (obj == (PyObject *)(&PyComplex_Type)) { PyComplex_Type.tp_as_number = PyCDoubleArrType_Type.tp_as_number; #if !defined(NPY_PY3K) PyComplex_Type.tp_compare = PyCDoubleArrType_Type.tp_compare; #endif 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 !defined(NPY_PY3K) 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 #endif if (obj == (PyObject *)(&PyFloat_Type)) { PyFloat_Type.tp_as_number = saved_tables[3]; #if !defined(NPY_PY3K) PyFloat_Type.tp_compare = saved_tables[4]; #endif PyFloat_Type.tp_richcompare = saved_tables[5]; } else if (obj == (PyObject *)(&PyComplex_Type)) { PyComplex_Type.tp_as_number = saved_tables[6]; #if !defined(NPY_PY3K) PyComplex_Type.tp_compare = saved_tables[7]; #endif 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 !defined(NPY_PY3K) 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 #endif if (obj == (PyObject *)(&PyFloat_Type)) { PyDoubleArrType_Type.tp_as_number = saved_tables[3]; #if !defined(NPY_PY3K) PyDoubleArrType_Type.tp_compare = saved_tables[4]; #endif PyDoubleArrType_Type.tp_richcompare = saved_tables[5]; } else if (obj == (PyObject *)(&PyComplex_Type)) { PyCDoubleArrType_Type.tp_as_number = saved_tables[6]; #if !defined(NPY_PY3K) PyCDoubleArrType_Type.tp_compare = saved_tables[7]; #endif 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 !defined(NPY_PY3K) 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 #endif if (obj == (PyObject *)(&PyFloat_Type)) { PyDoubleArrType_Type.tp_as_number = saved_tables_arrtype[3]; #if !defined(NPY_PY3K) PyDoubleArrType_Type.tp_compare = saved_tables_arrtype[4]; #endif PyDoubleArrType_Type.tp_richcompare = saved_tables_arrtype[5]; } else if (obj == (PyObject *)(&PyComplex_Type)) { PyCDoubleArrType_Type.tp_as_number = saved_tables_arrtype[6]; #if !defined(NPY_PY3K) PyCDoubleArrType_Type.tp_compare = saved_tables_arrtype[7]; #endif 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} }; #if defined(NPY_PY3K) static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "scalarmath", NULL, -1, methods, NULL, NULL, NULL, NULL }; #endif #if defined(NPY_PY3K) #define RETVAL m PyMODINIT_FUNC PyInit_scalarmath(void) #else #define RETVAL PyMODINIT_FUNC initscalarmath(void) #endif { #if defined(NPY_PY3K) PyObject *m = PyModule_Create(&moduledef); if (!m) { return NULL; } #else Py_InitModule("scalarmath", methods); #endif import_array(); import_umath(); if (get_functions() < 0) { return RETVAL; } add_scalarmath(); #if !defined(NPY_PY3K) saved_tables[0] = PyInt_Type.tp_as_number; saved_tables[1] = PyInt_Type.tp_compare; saved_tables[2] = PyInt_Type.tp_richcompare; #endif saved_tables[3] = PyFloat_Type.tp_as_number; #if !defined(NPY_PY3K) saved_tables[4] = PyFloat_Type.tp_compare; #endif saved_tables[5] = PyFloat_Type.tp_richcompare; saved_tables[6] = PyComplex_Type.tp_as_number; #if !defined(NPY_PY3K) saved_tables[7] = PyComplex_Type.tp_compare; #endif saved_tables[8] = PyComplex_Type.tp_richcompare; return RETVAL; }