diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2012-02-03 15:29:18 -0700 |
---|---|---|
committer | Charles Harris <charlesr.harris@gmail.com> | 2012-02-04 17:54:37 -0700 |
commit | 91eed7a8e32ad42943472e9eef24955bee2a0976 (patch) | |
tree | 02bb00165940c74c3a9855d7d42ada613ed85486 /numpy/core/src | |
parent | 585d6ea0a84925a3f5d73b50bb9a4378ca54f27b (diff) | |
download | numpy-91eed7a8e32ad42943472e9eef24955bee2a0976.tar.gz |
MOV: Rename umathmodule.c.src umathmodule.c since it has no templates.
Update core/bscript and core/setup.py to reflect the name change and
remove umathmodule.c.src as a template file that needs to be converted.
Diffstat (limited to 'numpy/core/src')
-rw-r--r-- | numpy/core/src/umath/umathmodule.c | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/numpy/core/src/umath/umathmodule.c b/numpy/core/src/umath/umathmodule.c new file mode 100644 index 000000000..a6a9b7b2b --- /dev/null +++ b/numpy/core/src/umath/umathmodule.c @@ -0,0 +1,442 @@ +/* -*- c -*- */ + +/* + * vim:syntax=c + */ + +/* + ***************************************************************************** + ** INCLUDES ** + ***************************************************************************** + */ + +/* + * _UMATHMODULE IS needed in __ufunc_api.h, included from numpy/ufuncobject.h. + * This is a mess and it would be nice to fix it. It has nothing to do with + * __ufunc_api.c + */ +#define _UMATHMODULE +#define NPY_NO_DEPRECATED_API + +#include "Python.h" + +#include "npy_config.h" +#ifdef ENABLE_SEPARATE_COMPILATION +#define PY_ARRAY_UNIQUE_SYMBOL _npy_umathmodule_ARRAY_API +#endif + +#include "numpy/ndarrayobject.h" +#include "numpy/ufuncobject.h" +#include "abstract.h" + +#include "numpy/npy_math.h" + +/* + ***************************************************************************** + ** INCLUDE GENERATED CODE ** + ***************************************************************************** + */ +#include "funcs.inc" +#include "loops.h" +#include "ufunc_object.h" +#include "ufunc_type_resolution.h" +#include "__umath_generated.c" +#include "__ufunc_api.c" + +static PyUFuncGenericFunction pyfunc_functions[] = {PyUFunc_On_Om}; + +static int +object_ufunc_type_resolver(PyUFuncObject *ufunc, + NPY_CASTING casting, + PyArrayObject **operands, + PyObject *type_tup, + PyArray_Descr **out_dtypes) +{ + int i, nop = ufunc->nin + ufunc->nout; + PyArray_Descr *obj_dtype; + + obj_dtype = PyArray_DescrFromType(NPY_OBJECT); + if (obj_dtype == NULL) { + return -1; + } + + for (i = 0; i < nop; ++i) { + Py_INCREF(obj_dtype); + out_dtypes[i] = obj_dtype; + } + + return 0; +} + +static int +object_ufunc_loop_selector(PyUFuncObject *ufunc, + PyArray_Descr **NPY_UNUSED(dtypes), + PyUFuncGenericFunction *out_innerloop, + void **out_innerloopdata, + int *out_needs_api) +{ + *out_innerloop = ufunc->functions[0]; + *out_innerloopdata = ufunc->data[0]; + *out_needs_api = 1; + + return 0; +} + +static PyObject * +ufunc_frompyfunc(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *NPY_UNUSED(kwds)) { + /* Keywords are ignored for now */ + + PyObject *function, *pyname = NULL; + int nin, nout, i; + PyUFunc_PyFuncData *fdata; + PyUFuncObject *self; + char *fname, *str; + Py_ssize_t fname_len = -1; + int offset[2]; + + if (!PyArg_ParseTuple(args, "Oii", &function, &nin, &nout)) { + return NULL; + } + if (!PyCallable_Check(function)) { + PyErr_SetString(PyExc_TypeError, "function must be callable"); + return NULL; + } + self = PyArray_malloc(sizeof(PyUFuncObject)); + if (self == NULL) { + return NULL; + } + PyObject_Init((PyObject *)self, &PyUFunc_Type); + + self->userloops = NULL; + self->nin = nin; + self->nout = nout; + self->nargs = nin + nout; + self->identity = PyUFunc_None; + self->functions = pyfunc_functions; + self->ntypes = 1; + self->check_return = 0; + + /* generalized ufunc */ + self->core_enabled = 0; + self->core_num_dim_ix = 0; + self->core_num_dims = NULL; + self->core_dim_ixs = NULL; + self->core_offsets = NULL; + self->core_signature = NULL; + + self->type_resolver = &object_ufunc_type_resolver; + self->legacy_inner_loop_selector = &object_ufunc_loop_selector; + + pyname = PyObject_GetAttrString(function, "__name__"); + if (pyname) { + (void) PyString_AsStringAndSize(pyname, &fname, &fname_len); + } + if (PyErr_Occurred()) { + fname = "?"; + fname_len = 1; + PyErr_Clear(); + } + + /* + * self->ptr holds a pointer for enough memory for + * self->data[0] (fdata) + * self->data + * self->name + * self->types + * + * To be safest, all of these need their memory aligned on void * pointers + * Therefore, we may need to allocate extra space. + */ + offset[0] = sizeof(PyUFunc_PyFuncData); + i = (sizeof(PyUFunc_PyFuncData) % sizeof(void *)); + if (i) { + offset[0] += (sizeof(void *) - i); + } + offset[1] = self->nargs; + i = (self->nargs % sizeof(void *)); + if (i) { + offset[1] += (sizeof(void *)-i); + } + self->ptr = PyArray_malloc(offset[0] + offset[1] + sizeof(void *) + + (fname_len + 14)); + if (self->ptr == NULL) { + Py_XDECREF(pyname); + return PyErr_NoMemory(); + } + Py_INCREF(function); + self->obj = function; + fdata = (PyUFunc_PyFuncData *)(self->ptr); + fdata->nin = nin; + fdata->nout = nout; + fdata->callable = function; + + self->data = (void **)(((char *)self->ptr) + offset[0]); + self->data[0] = (void *)fdata; + self->types = (char *)self->data + sizeof(void *); + for (i = 0; i < self->nargs; i++) { + self->types[i] = NPY_OBJECT; + } + str = self->types + offset[1]; + memcpy(str, fname, fname_len); + memcpy(str+fname_len, " (vectorized)", 14); + self->name = str; + + Py_XDECREF(pyname); + + /* Do a better job someday */ + self->doc = "dynamic ufunc based on a python function"; + + return (PyObject *)self; +} + +/* + ***************************************************************************** + ** SETUP UFUNCS ** + ***************************************************************************** + */ + +/* Less automated additions to the ufuncs */ + +static PyUFuncGenericFunction frexp_functions[] = { +#ifdef HAVE_FREXPF + HALF_frexp, + FLOAT_frexp, +#endif + DOUBLE_frexp +#ifdef HAVE_FREXPL + ,LONGDOUBLE_frexp +#endif +}; + +static void * blank3_data[] = { (void *)NULL, (void *)NULL, (void *)NULL}; +static void * blank6_data[] = { (void *)NULL, (void *)NULL, (void *)NULL, + (void *)NULL, (void *)NULL, (void *)NULL}; +static char frexp_signatures[] = { +#ifdef HAVE_FREXPF + NPY_HALF, NPY_HALF, NPY_INT, + NPY_FLOAT, NPY_FLOAT, NPY_INT, +#endif + NPY_DOUBLE, NPY_DOUBLE, NPY_INT +#ifdef HAVE_FREXPL + ,NPY_LONGDOUBLE, NPY_LONGDOUBLE, NPY_INT +#endif +}; + +#if NPY_SIZEOF_LONG == NPY_SIZEOF_INT +#define LDEXP_LONG(typ) typ##_ldexp +#else +#define LDEXP_LONG(typ) typ##_ldexp_long +#endif + +static PyUFuncGenericFunction ldexp_functions[] = { +#ifdef HAVE_LDEXPF + HALF_ldexp, + FLOAT_ldexp, + LDEXP_LONG(HALF), + LDEXP_LONG(FLOAT), +#endif + DOUBLE_ldexp, + LDEXP_LONG(DOUBLE) +#ifdef HAVE_LDEXPL + , + LONGDOUBLE_ldexp, + LDEXP_LONG(LONGDOUBLE) +#endif +}; + +static char ldexp_signatures[] = { +#ifdef HAVE_LDEXPF + NPY_HALF, NPY_INT, NPY_HALF, + NPY_FLOAT, NPY_INT, NPY_FLOAT, + NPY_HALF, NPY_LONG, NPY_HALF, + NPY_FLOAT, NPY_LONG, NPY_FLOAT, +#endif + NPY_DOUBLE, NPY_INT, NPY_DOUBLE, + NPY_DOUBLE, NPY_LONG, NPY_DOUBLE +#ifdef HAVE_LDEXPL + ,NPY_LONGDOUBLE, NPY_INT, NPY_LONGDOUBLE + ,NPY_LONGDOUBLE, NPY_LONG, NPY_LONGDOUBLE +#endif +}; + +static void +InitOtherOperators(PyObject *dictionary) { + PyObject *f; + int num; + + num = sizeof(frexp_functions) / sizeof(frexp_functions[0]); + f = PyUFunc_FromFuncAndData(frexp_functions, blank3_data, + frexp_signatures, num, + 1, 2, PyUFunc_None, "frexp", + "Split the number, x, into a normalized"\ + " fraction (y1) and exponent (y2)",0); + PyDict_SetItemString(dictionary, "frexp", f); + Py_DECREF(f); + + num = sizeof(ldexp_functions) / sizeof(ldexp_functions[0]); + f = PyUFunc_FromFuncAndData(ldexp_functions, blank6_data, ldexp_signatures, num, + 2, 1, PyUFunc_None, "ldexp", + "Compute y = x1 * 2**x2.",0); + PyDict_SetItemString(dictionary, "ldexp", f); + Py_DECREF(f); + +#if defined(NPY_PY3K) + f = PyDict_GetItemString(dictionary, "true_divide"); + PyDict_SetItemString(dictionary, "divide", f); +#endif + return; +} + +/* Setup the umath module */ +/* Remove for time being, it is declared in __ufunc_api.h */ +/*static PyTypeObject PyUFunc_Type;*/ + +static struct PyMethodDef methods[] = { + {"frompyfunc", + (PyCFunction) ufunc_frompyfunc, + METH_VARARGS | METH_KEYWORDS, NULL}, + {"seterrobj", + (PyCFunction) ufunc_seterr, + METH_VARARGS, NULL}, + {"geterrobj", + (PyCFunction) ufunc_geterr, + METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL} /* sentinel */ +}; + + +#if defined(NPY_PY3K) +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "umath", + NULL, + -1, + methods, + NULL, + NULL, + NULL, + NULL +}; +#endif + +#include <stdio.h> + +#if defined(NPY_PY3K) +#define RETVAL m +PyObject *PyInit_umath(void) +#else +#define RETVAL +PyMODINIT_FUNC initumath(void) +#endif +{ + PyObject *m, *d, *s, *s2, *c_api; + int UFUNC_FLOATING_POINT_SUPPORT = 1; + +#ifdef NO_UFUNC_FLOATING_POINT_SUPPORT + UFUNC_FLOATING_POINT_SUPPORT = 0; +#endif + /* Create the module and add the functions */ +#if defined(NPY_PY3K) + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule("umath", methods); +#endif + if (!m) { + return RETVAL; + } + + /* Import the array */ + if (_import_array() < 0) { + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, + "umath failed: Could not import array core."); + } + return RETVAL; + } + + /* Initialize the types */ + if (PyType_Ready(&PyUFunc_Type) < 0) + return RETVAL; + + /* Add some symbolic constants to the module */ + d = PyModule_GetDict(m); + + c_api = NpyCapsule_FromVoidPtr((void *)PyUFunc_API, NULL); + if (PyErr_Occurred()) { + goto err; + } + PyDict_SetItemString(d, "_UFUNC_API", c_api); + Py_DECREF(c_api); + if (PyErr_Occurred()) { + goto err; + } + + s = PyString_FromString("0.4.0"); + PyDict_SetItemString(d, "__version__", s); + Py_DECREF(s); + + /* Load the ufunc operators into the array module's namespace */ + InitOperators(d); + + InitOtherOperators(d); + + PyDict_SetItemString(d, "pi", s = PyFloat_FromDouble(NPY_PI)); + Py_DECREF(s); + PyDict_SetItemString(d, "e", s = PyFloat_FromDouble(exp(1.0))); + Py_DECREF(s); + +#define ADDCONST(str) PyModule_AddIntConstant(m, #str, UFUNC_##str) +#define ADDSCONST(str) PyModule_AddStringConstant(m, "UFUNC_" #str, UFUNC_##str) + + ADDCONST(ERR_IGNORE); + ADDCONST(ERR_WARN); + ADDCONST(ERR_CALL); + ADDCONST(ERR_RAISE); + ADDCONST(ERR_PRINT); + ADDCONST(ERR_LOG); + ADDCONST(ERR_DEFAULT); + ADDCONST(ERR_DEFAULT2); + + ADDCONST(SHIFT_DIVIDEBYZERO); + ADDCONST(SHIFT_OVERFLOW); + ADDCONST(SHIFT_UNDERFLOW); + ADDCONST(SHIFT_INVALID); + + ADDCONST(FPE_DIVIDEBYZERO); + ADDCONST(FPE_OVERFLOW); + ADDCONST(FPE_UNDERFLOW); + ADDCONST(FPE_INVALID); + + ADDCONST(FLOATING_POINT_SUPPORT); + + ADDSCONST(PYVALS_NAME); + +#undef ADDCONST +#undef ADDSCONST + PyModule_AddIntConstant(m, "UFUNC_BUFSIZE_DEFAULT", (long)NPY_BUFSIZE); + + PyModule_AddObject(m, "PINF", PyFloat_FromDouble(NPY_INFINITY)); + PyModule_AddObject(m, "NINF", PyFloat_FromDouble(-NPY_INFINITY)); + PyModule_AddObject(m, "PZERO", PyFloat_FromDouble(NPY_PZERO)); + PyModule_AddObject(m, "NZERO", PyFloat_FromDouble(NPY_NZERO)); + PyModule_AddObject(m, "NAN", PyFloat_FromDouble(NPY_NAN)); + + s = PyDict_GetItemString(d, "conjugate"); + s2 = PyDict_GetItemString(d, "remainder"); + /* Setup the array object's numerical structures with appropriate + ufuncs in d*/ + PyArray_SetNumericOps(d); + + PyDict_SetItemString(d, "conj", s); + PyDict_SetItemString(d, "mod", s2); + + return RETVAL; + + err: + /* Check for errors */ + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_RuntimeError, + "cannot load umath module."); + } + return RETVAL; +} |