/* -*- c -*- */ /* * This file is for the definitions of the non-c99 functions used in ufuncs. * All the complex ufuncs are defined here along with a smattering of real and * object functions. */ #define NPY_NO_DEPRECATED_API NPY_API_VERSION #include "npy_import.h" #include "npy_static_data.h" #include "multiarraymodule.h" /* ***************************************************************************** ** PYTHON OBJECT FUNCTIONS ** ***************************************************************************** */ static PyObject * Py_square(PyObject *o) { return PyNumber_Multiply(o, o); } static PyObject * Py_get_one(PyObject *NPY_UNUSED(o)) { return PyLong_FromLong(1); } static PyObject * Py_reciprocal(PyObject *o) { PyObject *one = PyLong_FromLong(1); PyObject *result; if (!one) { return NULL; } result = PyNumber_TrueDivide(one, o); Py_DECREF(one); return result; } /* * Define numpy version of PyNumber_Power as binary function. */ static PyObject * npy_ObjectPower(PyObject *x, PyObject *y) { return PyNumber_Power(x, y, Py_None); } /**begin repeat * #Kind = Max, Min# * #OP = Py_GE, Py_LE# */ static PyObject * npy_Object@Kind@(PyObject *i1, PyObject *i2) { PyObject *result; int cmp; cmp = PyObject_RichCompareBool(i1, i2, @OP@); if (cmp < 0) { return NULL; } if (cmp == 1) { result = i1; } else { result = i2; } Py_INCREF(result); return result; } /**end repeat**/ /* Emulates Python's 'a or b' behavior */ static PyObject * npy_ObjectLogicalOr(PyObject *i1, PyObject *i2) { if (i1 == NULL) { Py_XINCREF(i2); return i2; } else if (i2 == NULL) { Py_INCREF(i1); return i1; } else { int retcode = PyObject_IsTrue(i1); if (retcode == -1) { return NULL; } else if (retcode) { Py_INCREF(i1); return i1; } else { Py_INCREF(i2); return i2; } } } /* Emulates Python's 'a and b' behavior */ static PyObject * npy_ObjectLogicalAnd(PyObject *i1, PyObject *i2) { if (i1 == NULL) { return NULL; } else if (i2 == NULL) { return NULL; } else { int retcode = PyObject_IsTrue(i1); if (retcode == -1) { return NULL; } else if (!retcode) { Py_INCREF(i1); return i1; } else { Py_INCREF(i2); return i2; } } } /* Emulates Python's 'not b' behavior */ static PyObject * npy_ObjectLogicalNot(PyObject *i1) { if (i1 == NULL) { return NULL; } else { int retcode = PyObject_Not(i1); if (retcode == -1) { return NULL; } else if (retcode) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } } static PyObject * npy_ObjectFloor(PyObject *obj) { return PyObject_CallFunction(npy_static_pydata.math_floor_func, "O", obj); } static PyObject * npy_ObjectCeil(PyObject *obj) { return PyObject_CallFunction(npy_static_pydata.math_ceil_func, "O", obj); } static PyObject * npy_ObjectTrunc(PyObject *obj) { return PyObject_CallFunction(npy_static_pydata.math_trunc_func, "O", obj); } static PyObject * npy_ObjectGCD(PyObject *i1, PyObject *i2) { PyObject *gcd = NULL; /* use math.gcd if valid on the provided types */ { gcd = PyObject_CallFunction(npy_static_pydata.math_gcd_func, "OO", i1, i2); if (gcd != NULL) { return gcd; } /* silence errors, and fall back on pure-python gcd */ PyErr_Clear(); } /* otherwise, use our internal one, written in python */ { if (npy_cache_import_runtime("numpy._core._internal", "_gcd", &npy_runtime_imports.internal_gcd_func) == -1) { return NULL; } gcd = PyObject_CallFunction(npy_runtime_imports.internal_gcd_func, "OO", i1, i2); if (gcd == NULL) { return NULL; } /* _gcd has some unusual behaviour regarding sign */ Py_SETREF(gcd, PyNumber_Absolute(gcd)); return gcd; } } static PyObject * npy_ObjectLCM(PyObject *i1, PyObject *i2) { /* lcm(a, b) = abs(a // gcd(a, b) * b) */ PyObject *gcd = npy_ObjectGCD(i1, i2); PyObject *tmp; if(gcd == NULL) { return NULL; } /* Floor divide preserves integer types - we know the division will have * no remainder */ tmp = PyNumber_FloorDivide(i1, gcd); Py_DECREF(gcd); if(tmp == NULL) { return NULL; } Py_SETREF(tmp, PyNumber_Multiply(tmp, i2)); if(tmp == NULL) { return NULL; } /* even though we fix gcd to be positive, we need to do it again here */ Py_SETREF(tmp, PyNumber_Absolute(tmp)); return tmp; } static PyObject * npy_ObjectClip(PyObject *arr, PyObject *min, PyObject *max) { PyObject *o = npy_ObjectMax(arr, min); if (o == NULL) { return NULL; } Py_SETREF(o, npy_ObjectMin(o, max)); return o; } /* ***************************************************************************** ** COMPLEX FUNCTIONS ** ***************************************************************************** */ /* * Don't pass structures between functions (only pointers) because how * structures are passed is compiler dependent and could cause segfaults if * umath_ufunc_object.inc is compiled with a different compiler than an * extension that makes use of the UFUNC API */ /**begin repeat * * #NAME = CFLOAT, CDOUBLE, CLONGDOUBLE# * #ctype = npy_cfloat, npy_cdouble, npy_clongdouble# * #ftype = npy_float, npy_double, npy_longdouble# * #c = f, ,l# */ static void nc_neg@c@(@ctype@ *a, @ctype@ *r) { npy_csetreal@c@(r, -npy_creal@c@(*a)); npy_csetimag@c@(r, -npy_cimag@c@(*a)); return; } static void nc_pos@c@(@ctype@ *a, @ctype@ *r) { npy_csetreal@c@(r, +npy_creal@c@(*a)); npy_csetimag@c@(r, +npy_cimag@c@(*a)); return; } static void nc_sqrt@c@(@ctype@ *x, @ctype@ *r) { *r = npy_csqrt@c@(*x); return; } static void nc_rint@c@(@ctype@ *x, @ctype@ *r) { npy_csetreal@c@(r, npy_rint@c@(npy_creal@c@(*x))); npy_csetimag@c@(r, npy_rint@c@(npy_cimag@c@(*x))); } static void nc_log@c@(@ctype@ *x, @ctype@ *r) { *r = npy_clog@c@(*x); return; } static void nc_log1p@c@(@ctype@ *x, @ctype@ *r) { @ftype@ l = npy_hypot@c@(npy_creal@c@(*x) + 1,npy_cimag@c@(*x)); npy_csetimag@c@(r, npy_atan2@c@(npy_cimag@c@(*x), npy_creal@c@(*x) + 1)); npy_csetreal@c@(r, npy_log@c@(l)); return; } static void nc_exp@c@(@ctype@ *x, @ctype@ *r) { *r = npy_cexp@c@(*x); return; } static void nc_exp2@c@(@ctype@ *x, @ctype@ *r) { @ctype@ a; npy_csetreal@c@(&a, npy_creal@c@(*x)*NPY_LOGE2@c@); npy_csetimag@c@(&a, npy_cimag@c@(*x)*NPY_LOGE2@c@); nc_exp@c@(&a, r); return; } static void nc_expm1@c@(@ctype@ *x, @ctype@ *r) { @ftype@ a = npy_sin@c@(npy_cimag@c@(*x) / 2); npy_csetreal@c@(r, npy_expm1@c@(npy_creal@c@(*x)) * npy_cos@c@(npy_cimag@c@(*x)) - 2 * a * a); npy_csetimag@c@(r,npy_exp@c@(npy_creal@c@(*x)) * npy_sin@c@(npy_cimag@c@(*x))); return; } static void nc_pow@c@(@ctype@ *a, @ctype@ *b, @ctype@ *r) { *r = npy_cpow@c@(*a, *b); return; } static void nc_acos@c@(@ctype@ *x, @ctype@ *r) { *r = npy_cacos@c@(*x); return; } static void nc_acosh@c@(@ctype@ *x, @ctype@ *r) { *r = npy_cacosh@c@(*x); return; } static void nc_asin@c@(@ctype@ *x, @ctype@ *r) { *r = npy_casin@c@(*x); return; } static void nc_asinh@c@(@ctype@ *x, @ctype@ *r) { *r = npy_casinh@c@(*x); return; } static void nc_atan@c@(@ctype@ *x, @ctype@ *r) { *r = npy_catan@c@(*x); return; } static void nc_atanh@c@(@ctype@ *x, @ctype@ *r) { *r = npy_catanh@c@(*x); return; } static void nc_cos@c@(@ctype@ *x, @ctype@ *r) { *r = npy_ccos@c@(*x); return; } static void nc_cosh@c@(@ctype@ *x, @ctype@ *r) { *r = npy_ccosh@c@(*x); return; } static void nc_log10@c@(@ctype@ *x, @ctype@ *r) { nc_log@c@(x, r); npy_csetreal@c@(r, npy_creal@c@(*r) * NPY_LOG10E@c@); npy_csetimag@c@(r, npy_cimag@c@(*r) * NPY_LOG10E@c@); return; } static void nc_log2@c@(@ctype@ *x, @ctype@ *r) { nc_log@c@(x, r); npy_csetreal@c@(r, npy_creal@c@(*r) * NPY_LOG2E@c@); npy_csetimag@c@(r, npy_cimag@c@(*r) * NPY_LOG2E@c@); return; } static void nc_sin@c@(@ctype@ *x, @ctype@ *r) { *r = npy_csin@c@(*x); return; } static void nc_sinh@c@(@ctype@ *x, @ctype@ *r) { *r = npy_csinh@c@(*x); return; } static void nc_tan@c@(@ctype@ *x, @ctype@ *r) { *r = npy_ctan@c@(*x); return; } static void nc_tanh@c@(@ctype@ *x, @ctype@ *r) { *r = npy_ctanh@c@(*x); return; } /**end repeat**/