[pypy-commit] pypy ufuncapi: cleanup, add failing test that mimics numpy.linalg.inv's signature

mattip noreply at buildbot.pypy.org
Fri Oct 10 16:13:45 CEST 2014


Author: mattip <matti.picus at gmail.com>
Branch: ufuncapi
Changeset: r73883:0e380b57db19
Date: 2014-10-10 17:05 +0300
http://bitbucket.org/pypy/pypy/changeset/0e380b57db19/

Log:	cleanup, add failing test that mimics numpy.linalg.inv's signature
	showing there is much more to be done to finish this API

diff --git a/pypy/module/cpyext/include/numpy/__ufunc_api.h b/pypy/module/cpyext/include/numpy/__ufunc_api.h
deleted file mode 100644
--- a/pypy/module/cpyext/include/numpy/__ufunc_api.h
+++ /dev/null
@@ -1,328 +0,0 @@
-
-#ifdef _UMATHMODULE
-
-#ifdef NPY_ENABLE_SEPARATE_COMPILATION
-extern NPY_NO_EXPORT PyTypeObject PyUFunc_Type;
-#else
-NPY_NO_EXPORT PyTypeObject PyUFunc_Type;
-#endif
-
-#ifdef NPY_ENABLE_SEPARATE_COMPILATION
-    extern NPY_NO_EXPORT PyTypeObject PyUFunc_Type;
-#else
-    NPY_NO_EXPORT PyTypeObject PyUFunc_Type;
-#endif
-
-NPY_NO_EXPORT PyObject * PyUFunc_FromFuncAndData \
-       (PyUFuncGenericFunction *, void **, char *, int, int, int, int, char *, char *, int);
-NPY_NO_EXPORT int PyUFunc_RegisterLoopForType \
-       (PyUFuncObject *, int, PyUFuncGenericFunction, int *, void *);
-NPY_NO_EXPORT int PyUFunc_GenericFunction \
-       (PyUFuncObject *, PyObject *, PyObject *, PyArrayObject **);
-NPY_NO_EXPORT void PyUFunc_f_f_As_d_d \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_d_d \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_f_f \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_g_g \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_F_F_As_D_D \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_F_F \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_D_D \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_G_G \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_O_O \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_ff_f_As_dd_d \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_ff_f \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_dd_d \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_gg_g \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_FF_F_As_DD_D \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_DD_D \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_FF_F \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_GG_G \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_OO_O \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_O_O_method \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_OO_O_method \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_On_Om \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT int PyUFunc_GetPyValues \
-       (char *, int *, int *, PyObject **);
-NPY_NO_EXPORT int PyUFunc_checkfperr \
-       (int, PyObject *, int *);
-NPY_NO_EXPORT void PyUFunc_clearfperr \
-       (void);
-NPY_NO_EXPORT int PyUFunc_getfperr \
-       (void);
-NPY_NO_EXPORT int PyUFunc_handlefperr \
-       (int, PyObject *, int, int *);
-NPY_NO_EXPORT int PyUFunc_ReplaceLoopBySignature \
-       (PyUFuncObject *, PyUFuncGenericFunction, int *, PyUFuncGenericFunction *);
-NPY_NO_EXPORT PyObject * PyUFunc_FromFuncAndDataAndSignature \
-       (PyUFuncGenericFunction *, void **, char *, int, int, int, int, char *, char *, int, const char *);
-NPY_NO_EXPORT int PyUFunc_SetUsesArraysAsData \
-       (void **, size_t);
-NPY_NO_EXPORT void PyUFunc_e_e \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_e_e_As_f_f \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_e_e_As_d_d \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_ee_e \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_ee_e_As_ff_f \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT void PyUFunc_ee_e_As_dd_d \
-       (char **, npy_intp *, npy_intp *, void *);
-NPY_NO_EXPORT int PyUFunc_DefaultTypeResolver \
-       (PyUFuncObject *, NPY_CASTING, PyArrayObject **, PyObject *, PyArray_Descr **);
-NPY_NO_EXPORT int PyUFunc_ValidateCasting \
-       (PyUFuncObject *, NPY_CASTING, PyArrayObject **, PyArray_Descr **);
-NPY_NO_EXPORT int PyUFunc_RegisterLoopForDescr \
-       (PyUFuncObject *, PyArray_Descr *, PyUFuncGenericFunction, PyArray_Descr **, void *);
-
-#else
-
-#if defined(PY_UFUNC_UNIQUE_SYMBOL)
-#define PyUFunc_API PY_UFUNC_UNIQUE_SYMBOL
-#endif
-
-#if defined(NO_IMPORT) || defined(NO_IMPORT_UFUNC)
-extern void **PyUFunc_API;
-#else
-#if defined(PY_UFUNC_UNIQUE_SYMBOL)
-void **PyUFunc_API;
-#else
-static void **PyUFunc_API=NULL;
-#endif
-#endif
-
-#define PyUFunc_Type (*(PyTypeObject *)PyUFunc_API[0])
-#define PyUFunc_FromFuncAndData \
-        (*(PyObject * (*)(PyUFuncGenericFunction *, void **, char *, int, int, int, int, char *, char *, int)) \
-         PyUFunc_API[1])
-#define PyUFunc_RegisterLoopForType \
-        (*(int (*)(PyUFuncObject *, int, PyUFuncGenericFunction, int *, void *)) \
-         PyUFunc_API[2])
-#define PyUFunc_GenericFunction \
-        (*(int (*)(PyUFuncObject *, PyObject *, PyObject *, PyArrayObject **)) \
-         PyUFunc_API[3])
-#define PyUFunc_f_f_As_d_d \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[4])
-#define PyUFunc_d_d \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[5])
-#define PyUFunc_f_f \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[6])
-#define PyUFunc_g_g \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[7])
-#define PyUFunc_F_F_As_D_D \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[8])
-#define PyUFunc_F_F \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[9])
-#define PyUFunc_D_D \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[10])
-#define PyUFunc_G_G \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[11])
-#define PyUFunc_O_O \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[12])
-#define PyUFunc_ff_f_As_dd_d \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[13])
-#define PyUFunc_ff_f \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[14])
-#define PyUFunc_dd_d \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[15])
-#define PyUFunc_gg_g \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[16])
-#define PyUFunc_FF_F_As_DD_D \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[17])
-#define PyUFunc_DD_D \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[18])
-#define PyUFunc_FF_F \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[19])
-#define PyUFunc_GG_G \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[20])
-#define PyUFunc_OO_O \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[21])
-#define PyUFunc_O_O_method \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[22])
-#define PyUFunc_OO_O_method \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[23])
-#define PyUFunc_On_Om \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[24])
-#define PyUFunc_GetPyValues \
-        (*(int (*)(char *, int *, int *, PyObject **)) \
-         PyUFunc_API[25])
-#define PyUFunc_checkfperr \
-        (*(int (*)(int, PyObject *, int *)) \
-         PyUFunc_API[26])
-#define PyUFunc_clearfperr \
-        (*(void (*)(void)) \
-         PyUFunc_API[27])
-#define PyUFunc_getfperr \
-        (*(int (*)(void)) \
-         PyUFunc_API[28])
-#define PyUFunc_handlefperr \
-        (*(int (*)(int, PyObject *, int, int *)) \
-         PyUFunc_API[29])
-#define PyUFunc_ReplaceLoopBySignature \
-        (*(int (*)(PyUFuncObject *, PyUFuncGenericFunction, int *, PyUFuncGenericFunction *)) \
-         PyUFunc_API[30])
-#define PyUFunc_FromFuncAndDataAndSignature \
-        (*(PyObject * (*)(PyUFuncGenericFunction *, void **, char *, int, int, int, int, char *, char *, int, const char *)) \
-         PyUFunc_API[31])
-#define PyUFunc_SetUsesArraysAsData \
-        (*(int (*)(void **, size_t)) \
-         PyUFunc_API[32])
-#define PyUFunc_e_e \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[33])
-#define PyUFunc_e_e_As_f_f \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[34])
-#define PyUFunc_e_e_As_d_d \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[35])
-#define PyUFunc_ee_e \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[36])
-#define PyUFunc_ee_e_As_ff_f \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[37])
-#define PyUFunc_ee_e_As_dd_d \
-        (*(void (*)(char **, npy_intp *, npy_intp *, void *)) \
-         PyUFunc_API[38])
-#define PyUFunc_DefaultTypeResolver \
-        (*(int (*)(PyUFuncObject *, NPY_CASTING, PyArrayObject **, PyObject *, PyArray_Descr **)) \
-         PyUFunc_API[39])
-#define PyUFunc_ValidateCasting \
-        (*(int (*)(PyUFuncObject *, NPY_CASTING, PyArrayObject **, PyArray_Descr **)) \
-         PyUFunc_API[40])
-#define PyUFunc_RegisterLoopForDescr \
-        (*(int (*)(PyUFuncObject *, PyArray_Descr *, PyUFuncGenericFunction, PyArray_Descr **, void *)) \
-         PyUFunc_API[41])
-
-static int
-_import_umath(void)
-{
-  PyObject *numpy = PyImport_ImportModule("numpy.core.umath");
-  PyObject *c_api = NULL;
-
-  if (numpy == NULL) {
-      PyErr_SetString(PyExc_ImportError, "numpy.core.umath failed to import");
-      return -1;
-  }
-  c_api = PyObject_GetAttrString(numpy, "_UFUNC_API");
-  Py_DECREF(numpy);
-  if (c_api == NULL) {
-      PyErr_SetString(PyExc_AttributeError, "_UFUNC_API not found");
-      return -1;
-  }
-
-#if PY_VERSION_HEX >= 0x03000000
-  if (!PyCapsule_CheckExact(c_api)) {
-      PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is not PyCapsule object");
-      Py_DECREF(c_api);
-      return -1;
-  }
-  PyUFunc_API = (void **)PyCapsule_GetPointer(c_api, NULL);
-#else
-  if (!PyCObject_Check(c_api)) {
-      PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is not PyCObject object");
-      Py_DECREF(c_api);
-      return -1;
-  }
-  PyUFunc_API = (void **)PyCObject_AsVoidPtr(c_api);
-#endif
-  Py_DECREF(c_api);
-  if (PyUFunc_API == NULL) {
-      PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is NULL pointer");
-      return -1;
-  }
-  return 0;
-}
-
-#if PY_VERSION_HEX >= 0x03000000
-#define NUMPY_IMPORT_UMATH_RETVAL NULL
-#else
-#define NUMPY_IMPORT_UMATH_RETVAL
-#endif
-
-#define import_umath() \
-    do {\
-        UFUNC_NOFPE\
-        if (_import_umath() < 0) {\
-            PyErr_Print();\
-            PyErr_SetString(PyExc_ImportError,\
-                    "numpy.core.umath failed to import");\
-            return NUMPY_IMPORT_UMATH_RETVAL;\
-        }\
-    } while(0)
-
-#define import_umath1(ret) \
-    do {\
-        UFUNC_NOFPE\
-        if (_import_umath() < 0) {\
-            PyErr_Print();\
-            PyErr_SetString(PyExc_ImportError,\
-                    "numpy.core.umath failed to import");\
-            return ret;\
-        }\
-    } while(0)
-
-#define import_umath2(ret, msg) \
-    do {\
-        UFUNC_NOFPE\
-        if (_import_umath() < 0) {\
-            PyErr_Print();\
-            PyErr_SetString(PyExc_ImportError, msg);\
-            return ret;\
-        }\
-    } while(0)
-
-#define import_ufunc() \
-    do {\
-        UFUNC_NOFPE\
-        if (_import_umath() < 0) {\
-            PyErr_Print();\
-            PyErr_SetString(PyExc_ImportError,\
-                    "numpy.core.umath failed to import");\
-        }\
-    } while(0)
-
-#endif
diff --git a/pypy/module/cpyext/include/numpy/ufuncobject.h b/pypy/module/cpyext/include/numpy/ufuncobject.h
deleted file mode 100644
--- a/pypy/module/cpyext/include/numpy/ufuncobject.h
+++ /dev/null
@@ -1,479 +0,0 @@
-#ifndef Py_UFUNCOBJECT_H
-#define Py_UFUNCOBJECT_H
-
-//#include <numpy/npy_math.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * The legacy generic inner loop for a standard element-wise or
- * generalized ufunc.
- */
-typedef void (*PyUFuncGenericFunction)
-            (char **args,
-             npy_intp *dimensions,
-             npy_intp *strides,
-             void *innerloopdata);
-
-/*
- * The most generic one-dimensional inner loop for
- * a standard element-wise ufunc. This typedef is also
- * more consistent with the other NumPy function pointer typedefs
- * than PyUFuncGenericFunction.
- */
-typedef void (PyUFunc_StridedInnerLoopFunc)(
-                char **dataptrs, npy_intp *strides,
-                npy_intp count,
-                NpyAuxData *innerloopdata);
-
-/*
- * The most generic one-dimensional inner loop for
- * a masked standard element-wise ufunc. "Masked" here means that it skips
- * doing calculations on any items for which the maskptr array has a true
- * value.
- */
-typedef void (PyUFunc_MaskedStridedInnerLoopFunc)(
-                char **dataptrs, npy_intp *strides,
-                char *maskptr, npy_intp mask_stride,
-                npy_intp count,
-                NpyAuxData *innerloopdata);
-
-/* Forward declaration for the type resolver and loop selector typedefs */
-struct _tagPyUFuncObject;
-
-/*
- * Given the operands for calling a ufunc, should determine the
- * calculation input and output data types and return an inner loop function.
- * This function should validate that the casting rule is being followed,
- * and fail if it is not.
- *
- * For backwards compatibility, the regular type resolution function does not
- * support auxiliary data with object semantics. The type resolution call
- * which returns a masked generic function returns a standard NpyAuxData
- * object, for which the NPY_AUXDATA_FREE and NPY_AUXDATA_CLONE macros
- * work.
- *
- * ufunc:             The ufunc object.
- * casting:           The 'casting' parameter provided to the ufunc.
- * operands:          An array of length (ufunc->nin + ufunc->nout),
- *                    with the output parameters possibly NULL.
- * type_tup:          Either NULL, or the type_tup passed to the ufunc.
- * out_dtypes:        An array which should be populated with new
- *                    references to (ufunc->nin + ufunc->nout) new
- *                    dtypes, one for each input and output. These
- *                    dtypes should all be in native-endian format.
- *
- * Should return 0 on success, -1 on failure (with exception set),
- * or -2 if Py_NotImplemented should be returned.
- */
-typedef int (PyUFunc_TypeResolutionFunc)(
-                                struct _tagPyUFuncObject *ufunc,
-                                NPY_CASTING casting,
-                                PyArrayObject **operands,
-                                PyObject *type_tup,
-                                PyArray_Descr **out_dtypes);
-
-/*
- * Given an array of DTypes as returned by the PyUFunc_TypeResolutionFunc,
- * and an array of fixed strides (the array will contain NPY_MAX_INTP for
- * strides which are not necessarily fixed), returns an inner loop
- * with associated auxiliary data.
- *
- * For backwards compatibility, there is a variant of the inner loop
- * selection which returns an inner loop irrespective of the strides,
- * and with a void* static auxiliary data instead of an NpyAuxData *
- * dynamically allocatable auxiliary data.
- *
- * ufunc:             The ufunc object.
- * dtypes:            An array which has been populated with dtypes,
- *                    in most cases by the type resolution funciton
- *                    for the same ufunc.
- * fixed_strides:     For each input/output, either the stride that
- *                    will be used every time the function is called
- *                    or NPY_MAX_INTP if the stride might change or
- *                    is not known ahead of time. The loop selection
- *                    function may use this stride to pick inner loops
- *                    which are optimized for contiguous or 0-stride
- *                    cases.
- * out_innerloop:     Should be populated with the correct ufunc inner
- *                    loop for the given type.
- * out_innerloopdata: Should be populated with the void* data to
- *                    be passed into the out_innerloop function.
- * out_needs_api:     If the inner loop needs to use the Python API,
- *                    should set the to 1, otherwise should leave
- *                    this untouched.
- */
-typedef int (PyUFunc_LegacyInnerLoopSelectionFunc)(
-                            struct _tagPyUFuncObject *ufunc,
-                            PyArray_Descr **dtypes,
-                            PyUFuncGenericFunction *out_innerloop,
-                            void **out_innerloopdata,
-                            int *out_needs_api);
-typedef int (PyUFunc_InnerLoopSelectionFunc)(
-                            struct _tagPyUFuncObject *ufunc,
-                            PyArray_Descr **dtypes,
-                            npy_intp *fixed_strides,
-                            PyUFunc_StridedInnerLoopFunc **out_innerloop,
-                            NpyAuxData **out_innerloopdata,
-                            int *out_needs_api);
-typedef int (PyUFunc_MaskedInnerLoopSelectionFunc)(
-                            struct _tagPyUFuncObject *ufunc,
-                            PyArray_Descr **dtypes,
-                            PyArray_Descr *mask_dtype,
-                            npy_intp *fixed_strides,
-                            npy_intp fixed_mask_stride,
-                            PyUFunc_MaskedStridedInnerLoopFunc **out_innerloop,
-                            NpyAuxData **out_innerloopdata,
-                            int *out_needs_api);
-
-typedef struct _tagPyUFuncObject {
-        PyObject_HEAD
-        /*
-         * nin: Number of inputs
-         * nout: Number of outputs
-         * nargs: Always nin + nout (Why is it stored?)
-         */
-        int nin, nout, nargs;
-
-        /* Identity for reduction, either PyUFunc_One or PyUFunc_Zero */
-        int identity;
-
-        /* Array of one-dimensional core loops */
-        PyUFuncGenericFunction *functions;
-        /* Array of funcdata that gets passed into the functions */
-        void **data;
-        /* The number of elements in 'functions' and 'data' */
-        int ntypes;
-
-        /* Does not appear to be used */
-        int check_return;
-
-        /* The name of the ufunc */
-        char *name;
-
-        /* Array of type numbers, of size ('nargs' * 'ntypes') */
-        char *types;
-
-        /* Documentation string */
-        char *doc;
-
-        void *ptr;
-        PyObject *obj;
-        PyObject *userloops;
-
-        /* generalized ufunc parameters */
-
-        /* 0 for scalar ufunc; 1 for generalized ufunc */
-        int core_enabled;
-        /* number of distinct dimension names in signature */
-        int core_num_dim_ix;
-
-        /*
-         * dimension indices of input/output argument k are stored in
-         * core_dim_ixs[core_offsets[k]..core_offsets[k]+core_num_dims[k]-1]
-         */
-
-        /* numbers of core dimensions of each argument */
-        int *core_num_dims;
-        /*
-         * dimension indices in a flatted form; indices
-         * are in the range of [0,core_num_dim_ix)
-         */
-        int *core_dim_ixs;
-        /*
-         * positions of 1st core dimensions of each
-         * argument in core_dim_ixs
-         */
-        int *core_offsets;
-        /* signature string for printing purpose */
-        char *core_signature;
-
-        /*
-         * A function which resolves the types and fills an array
-         * with the dtypes for the inputs and outputs.
-         */
-        PyUFunc_TypeResolutionFunc *type_resolver;
-        /*
-         * A function which returns an inner loop written for
-         * NumPy 1.6 and earlier ufuncs. This is for backwards
-         * compatibility, and may be NULL if inner_loop_selector
-         * is specified.
-         */
-        PyUFunc_LegacyInnerLoopSelectionFunc *legacy_inner_loop_selector;
-        /*
-         * A function which returns an inner loop for the new mechanism
-         * in NumPy 1.7 and later. If provided, this is used, otherwise
-         * if NULL the legacy_inner_loop_selector is used instead.
-         */
-        PyUFunc_InnerLoopSelectionFunc *inner_loop_selector;
-        /*
-         * A function which returns a masked inner loop for the ufunc.
-         */
-        PyUFunc_MaskedInnerLoopSelectionFunc *masked_inner_loop_selector;
-
-        /*
-         * List of flags for each operand when ufunc is called by nditer object.
-         * These flags will be used in addition to the default flags for each
-         * operand set by nditer object.
-         */
-        npy_uint32 *op_flags;
-
-        /*
-         * List of global flags used when ufunc is called by nditer object.
-         * These flags will be used in addition to the default global flags
-         * set by nditer object.
-         */
-        npy_uint32 iter_flags;
-} PyUFuncObject;
-
-#include "arrayobject.h"
-
-#define UFUNC_ERR_IGNORE 0
-#define UFUNC_ERR_WARN   1
-#define UFUNC_ERR_RAISE  2
-#define UFUNC_ERR_CALL   3
-#define UFUNC_ERR_PRINT  4
-#define UFUNC_ERR_LOG    5
-
-        /* Python side integer mask */
-
-#define UFUNC_MASK_DIVIDEBYZERO 0x07
-#define UFUNC_MASK_OVERFLOW 0x3f
-#define UFUNC_MASK_UNDERFLOW 0x1ff
-#define UFUNC_MASK_INVALID 0xfff
-
-#define UFUNC_SHIFT_DIVIDEBYZERO 0
-#define UFUNC_SHIFT_OVERFLOW     3
-#define UFUNC_SHIFT_UNDERFLOW    6
-#define UFUNC_SHIFT_INVALID      9
-
-
-/* platform-dependent code translates floating point
-   status to an integer sum of these values
-*/
-#define UFUNC_FPE_DIVIDEBYZERO  1
-#define UFUNC_FPE_OVERFLOW      2
-#define UFUNC_FPE_UNDERFLOW     4
-#define UFUNC_FPE_INVALID       8
-
-/* Error mode that avoids look-up (no checking) */
-#define UFUNC_ERR_DEFAULT       0
-
-#define UFUNC_OBJ_ISOBJECT      1
-#define UFUNC_OBJ_NEEDS_API     2
-
-   /* Default user error mode */
-#define UFUNC_ERR_DEFAULT2                               \
-        (UFUNC_ERR_WARN << UFUNC_SHIFT_DIVIDEBYZERO) +  \
-        (UFUNC_ERR_WARN << UFUNC_SHIFT_OVERFLOW) +      \
-        (UFUNC_ERR_WARN << UFUNC_SHIFT_INVALID)
-
-#if NPY_ALLOW_THREADS
-#define NPY_LOOP_BEGIN_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) _save = PyEval_SaveThread();} while (0);
-#define NPY_LOOP_END_THREADS   do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) PyEval_RestoreThread(_save);} while (0);
-#else
-#define NPY_LOOP_BEGIN_THREADS
-#define NPY_LOOP_END_THREADS
-#endif
-
-/*
- * UFunc has unit of 1, and the order of operations can be reordered
- * This case allows reduction with multiple axes at once.
- */
-#define PyUFunc_One 1
-/*
- * UFunc has unit of 0, and the order of operations can be reordered
- * This case allows reduction with multiple axes at once.
- */
-#define PyUFunc_Zero 0
-/*
- * UFunc has no unit, and the order of operations cannot be reordered.
- * This case does not allow reduction with multiple axes at once.
- */
-#define PyUFunc_None -1
-/*
- * UFunc has no unit, and the order of operations can be reordered
- * This case allows reduction with multiple axes at once.
- */
-#define PyUFunc_ReorderableNone -2
-
-#define UFUNC_REDUCE 0
-#define UFUNC_ACCUMULATE 1
-#define UFUNC_REDUCEAT 2
-#define UFUNC_OUTER 3
-
-
-typedef struct {
-        int nin;
-        int nout;
-        PyObject *callable;
-} PyUFunc_PyFuncData;
-
-/* A linked-list of function information for
-   user-defined 1-d loops.
- */
-typedef struct _loop1d_info {
-        PyUFuncGenericFunction func;
-        void *data;
-        int *arg_types;
-        struct _loop1d_info *next;
-        int nargs;
-        PyArray_Descr **arg_dtypes;
-} PyUFunc_Loop1d;
-
-
-#include "numpy/__ufunc_api.h"
-
-#define UFUNC_PYVALS_NAME "UFUNC_PYVALS"
-
-#define UFUNC_CHECK_ERROR(arg) \
-        do {if ((((arg)->obj & UFUNC_OBJ_NEEDS_API) && PyErr_Occurred()) || \
-            ((arg)->errormask && \
-             PyUFunc_checkfperr((arg)->errormask, \
-                                (arg)->errobj, \
-                                &(arg)->first))) \
-                goto fail;} while (0)
-
-/* This code checks the IEEE status flags in a platform-dependent way */
-/* Adapted from Numarray  */
-
-#if (defined(__unix__) || defined(unix)) && !defined(USG)
-#include <sys/param.h>
-#endif
-
-/*  OSF/Alpha (Tru64)  ---------------------------------------------*/
-#if defined(__osf__) && defined(__alpha)
-
-#include <machine/fpu.h>
-
-#define UFUNC_CHECK_STATUS(ret) { \
-        unsigned long fpstatus; \
-         \
-        fpstatus = ieee_get_fp_control(); \
-        /* clear status bits as well as disable exception mode if on */ \
-        ieee_set_fp_control( 0 ); \
-        ret = ((IEEE_STATUS_DZE & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
-                | ((IEEE_STATUS_OVF & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \
-                | ((IEEE_STATUS_UNF & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
-                | ((IEEE_STATUS_INV & fpstatus) ? UFUNC_FPE_INVALID : 0); \
-        }
-
-/* MS Windows -----------------------------------------------------*/
-#elif defined(_MSC_VER)
-
-#include <float.h>
-
-/* Clear the floating point exception default of Borland C++ */
-#if defined(__BORLANDC__)
-#define UFUNC_NOFPE _control87(MCW_EM, MCW_EM);
-#endif
-
-#if defined(_WIN64)
-#define UFUNC_CHECK_STATUS(ret) { \
-        int fpstatus = (int) _clearfp(); \
-         \
-        ret = ((SW_ZERODIVIDE & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
-                | ((SW_OVERFLOW & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \
-                | ((SW_UNDERFLOW & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
-                | ((SW_INVALID & fpstatus) ? UFUNC_FPE_INVALID : 0); \
-        }
-#else
-/* windows enables sse on 32 bit, so check both flags */
-#define UFUNC_CHECK_STATUS(ret) { \
-        int fpstatus, fpstatus2; \
-        _statusfp2(&fpstatus, &fpstatus2); \
-        _clearfp(); \
-        fpstatus |= fpstatus2; \
-         \
-        ret = ((SW_ZERODIVIDE & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
-                | ((SW_OVERFLOW & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \
-                | ((SW_UNDERFLOW & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
-                | ((SW_INVALID & fpstatus) ? UFUNC_FPE_INVALID : 0); \
-        }
-#endif
-
-/* Solaris --------------------------------------------------------*/
-/* --------ignoring SunOS ieee_flags approach, someone else can
-**         deal with that! */
-#elif defined(sun) || defined(__BSD__) || defined(__OpenBSD__) || \
-      (defined(__FreeBSD__) && (__FreeBSD_version < 502114)) || \
-      defined(__NetBSD__)
-#include <ieeefp.h>
-
-#define UFUNC_CHECK_STATUS(ret) { \
-        int fpstatus; \
-         \
-        fpstatus = (int) fpgetsticky(); \
-        ret = ((FP_X_DZ  & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
-                | ((FP_X_OFL & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \
-                | ((FP_X_UFL & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
-                | ((FP_X_INV & fpstatus) ? UFUNC_FPE_INVALID : 0); \
-        (void) fpsetsticky(0); \
-        }
-
-#elif defined(__GLIBC__) || defined(__APPLE__) || \
-      defined(__CYGWIN__) || defined(__MINGW32__) || \
-      (defined(__FreeBSD__) && (__FreeBSD_version >= 502114))
-
-#if defined(__GLIBC__) || defined(__APPLE__) || \
-    defined(__MINGW32__) || defined(__FreeBSD__)
-#include <fenv.h>
-#elif defined(__CYGWIN__)
-#include "numpy/fenv/fenv.h"
-#endif
-
-#define UFUNC_CHECK_STATUS(ret) { \
-        int fpstatus = (int) fetestexcept(FE_DIVBYZERO | FE_OVERFLOW | \
-                                          FE_UNDERFLOW | FE_INVALID); \
-        ret = ((FE_DIVBYZERO  & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
-                | ((FE_OVERFLOW   & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \
-                | ((FE_UNDERFLOW  & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
-                | ((FE_INVALID    & fpstatus) ? UFUNC_FPE_INVALID : 0); \
-        (void) feclearexcept(FE_DIVBYZERO | FE_OVERFLOW | \
-                             FE_UNDERFLOW | FE_INVALID); \
-}
-
-#elif defined(_AIX)
-
-#include <float.h>
-#include <fpxcp.h>
-
-#define UFUNC_CHECK_STATUS(ret) { \
-        fpflag_t fpstatus; \
- \
-        fpstatus = fp_read_flag(); \
-        ret = ((FP_DIV_BY_ZERO & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
-                | ((FP_OVERFLOW & fpstatus) ? UFUNC_FPE_OVERFLOW : 0)   \
-                | ((FP_UNDERFLOW & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
-                | ((FP_INVALID & fpstatus) ? UFUNC_FPE_INVALID : 0); \
-        fp_swap_flag(0); \
-}
-
-#else
-
-#define NO_FLOATING_POINT_SUPPORT
-#define UFUNC_CHECK_STATUS(ret) { \
-    ret = 0; \
-  }
-
-#endif
-
-/*
- * THESE MACROS ARE DEPRECATED.
- * Use npy_set_floatstatus_* in the npymath library.
- */
-#define generate_divbyzero_error() npy_set_floatstatus_divbyzero()
-#define generate_overflow_error() npy_set_floatstatus_overflow()
-
-  /* Make sure it gets defined if it isn't already */
-#ifndef UFUNC_NOFPE
-#define UFUNC_NOFPE
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* !Py_UFUNCOBJECT_H */
diff --git a/pypy/module/cpyext/ndarrayobject.py b/pypy/module/cpyext/ndarrayobject.py
--- a/pypy/module/cpyext/ndarrayobject.py
+++ b/pypy/module/cpyext/ndarrayobject.py
@@ -275,14 +275,20 @@
         steps = alloc_raw_storage(LONG_SIZE * len(args_w), track_allocation=False)
         for i in range(len(args_w)):
             arg_i = args_w[i]
-            assert isinstance(arg_i, W_NDimArray)
-            raw_storage_setitem(dataps, CCHARP_SIZE * i, rffi.cast(rffi.CCHARP, arg_i.implementation.storage))
-            #This assumes we iterate over the whole array (it should be a view...)
-            raw_storage_setitem(dims, LONG_SIZE * i, rffi.cast(rffi.LONG, arg_i.get_size()))
-            raw_storage_setitem(steps, LONG_SIZE * i, rffi.cast(rffi.LONG, arg_i.get_dtype().elsize))
+            if isinstance(arg_i, W_NDimArray):
+                raw_storage_setitem(dataps, CCHARP_SIZE * i,
+                        rffi.cast(rffi.CCHARP, arg_i.implementation.storage))
+                #This assumes we iterate over the whole array (it should be a view...)
+                raw_storage_setitem(dims, LONG_SIZE * i, rffi.cast(rffi.LONG, arg_i.get_size()))
+                raw_storage_setitem(steps, LONG_SIZE * i, rffi.cast(rffi.LONG, arg_i.get_dtype().elsize))
+            else:
+                raise OperationError(space.w_NotImplementedError,
+                         space.wrap("cannot call GenericUFunc with %r as arg %d" % (arg_i, i)))
         try:
-            self.func(rffi.cast(rffi.CArrayPtr(rffi.CCHARP), dataps),
-                      rffi.cast(npy_intpp, dims), rffi.cast(npy_intpp, steps), self.data)
+            arg1 = rffi.cast(rffi.CArrayPtr(rffi.CCHARP), dataps)
+            arg2 = rffi.cast(npy_intpp, dims)
+            arg3 = rffi.cast(npy_intpp, steps)
+            self.func(arg1, arg2, arg3, self.data)
         finally:
             free_raw_storage(dataps, track_allocation=False)
             free_raw_storage(dims, track_allocation=False)
@@ -295,7 +301,8 @@
 GenericUfunc = lltype.FuncType([rffi.CArrayPtr(rffi.CCHARP), npy_intpp, npy_intpp,
                                       rffi.VOIDP], lltype.Void)
 gufunctype = lltype.Ptr(GenericUfunc)
-# XXX single rffi.CArrayPtr(gufunctype) does not work, this does, why???
+# XXX single rffi.CArrayPtr(gufunctype) does not work, this does, is there
+# a problem with casting function pointers?
 @cpython_api([rffi.CArrayPtr(rffi.CArrayPtr(gufunctype)), rffi.VOIDP, rffi.CCHARP, Py_ssize_t, Py_ssize_t,
               Py_ssize_t, Py_ssize_t, rffi.CCHARP, rffi.CCHARP, Py_ssize_t,
               rffi.CCHARP], PyObject)
diff --git a/pypy/module/cpyext/test/test_ndarrayobject.py b/pypy/module/cpyext/test/test_ndarrayobject.py
--- a/pypy/module/cpyext/test/test_ndarrayobject.py
+++ b/pypy/module/cpyext/test/test_ndarrayobject.py
@@ -316,7 +316,7 @@
     def test_ufunc(self):
         from _numpypy.multiarray import arange
         mod = self.import_extension('foo', [
-                ("create_ufunc",  "METH_NOARGS",
+                ("create_ufunc_basic",  "METH_NOARGS",
                 """
                 PyUFuncGenericFunction funcs[] = {&double_times2, &int_times2};
                 char types[] = { NPY_DOUBLE,NPY_DOUBLE, NPY_INT, NPY_INT };
@@ -328,8 +328,27 @@
                 return retval;
                 """
                 ),
-                ], prologue='''#include "numpy/ndarraytypes.h"
-                #include <numpy/ufuncobject.h>
+                ("create_ufunc_signature", "METH_NOARGS",
+                """
+                PyUFuncGenericFunction funcs[] = {&double_times2, &int_times2};
+                char types[] = { NPY_DOUBLE,NPY_DOUBLE, NPY_INT, NPY_INT };
+                void *array_data[] = {NULL, NULL};
+                PyObject * retval;
+                retval = PyUFunc_FromFuncAndDataAndSignature(funcs,
+                                    array_data, types, 2, 1, 1, PyUFunc_None,
+                                    "times2", "times2_docstring", 0, "(m)->(m)");
+                return retval;
+                """
+                ),
+                ], prologue='''
+                #include "numpy/ndarraytypes.h"
+                /*#include <numpy/ufuncobject.h>*/
+                typedef void (*PyUFuncGenericFunction)
+                            (char **args,
+                             npy_intp *dimensions,
+                             npy_intp *strides,
+                             void *innerloopdata);
+                #define PyUFunc_None -1
                 void double_times2(char **args, npy_intp *dimensions,
                               npy_intp* steps, void* data)
                 {
@@ -372,7 +391,10 @@
                         out += out_step;
                     };
                 }; ''')
-        times2 = mod.create_ufunc()
+        times2 = mod.create_ufunc_basic()
         arr = arange(12, dtype='i').reshape(3, 4)
-        out = times2(arr)
+        out = times2(arr, sig='(d)->(d)', extobj=[0, 0, None])
         assert (out == arr * 2).all()
+        times2prime = mod.create_ufunc_signature()
+        out = times2prime(arr, sig='(d)->(d)', extobj=[0, 0, None])
+        assert (out == arr * 2).all()
diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py
--- a/pypy/module/micronumpy/ufuncs.py
+++ b/pypy/module/micronumpy/ufuncs.py
@@ -579,7 +579,6 @@
             # func is going to do all the work
             arglist = space.newlist(inargs + outargs)
             func = self.funcs[index]
-            arglist = space.newlist(inargs + outargs)
             space.call_args(func, Arguments.frompacked(space, arglist))
             if len(outargs) < 2:
                 return outargs0
@@ -1051,7 +1050,7 @@
         if not space.is_true(space.callable(w_func)):
             raise oefmt(space.w_TypeError, 'func must be callable')
         func = [w_func]
-    match_dtypes = False    
+    match_dtypes = False
     if space.is_none(w_dtypes) and not signature:
         raise oefmt(space.w_NotImplementedError,
              'object dtype requested but not implemented')
@@ -1061,7 +1060,7 @@
             if space.isinstance_w(_dtypes[0], space.w_str) and space.str_w(_dtypes[0]) == 'match':
                 dtypes = []
                 match_dtypes = True
-            else:    
+            else:
                 dtypes = [None]*len(_dtypes)
                 for i in range(len(dtypes)):
                     dtypes[i] = descriptor.decode_w_dtype(space, _dtypes[i])
@@ -1074,7 +1073,7 @@
     elif space.isinstance_w(w_identity, space.w_int):
         identity = \
             descriptor.get_dtype_cache(space).w_longdtype.box(space.int_w(w_identity))
-    else:        
+    else:
         raise oefmt(space.w_ValueError,
             'identity must be None or an int')
 


More information about the pypy-commit mailing list