1
/* -*- c -*- */
2

3
/*
4
 * vim:syntax=c
5
 */
6

7
/*
8
 *****************************************************************************
9
 **                            INCLUDES                                     **
10
 *****************************************************************************
11
 */
12

13
/*
14
 * _UMATHMODULE IS needed in __ufunc_api.h, included from numpy/ufuncobject.h.
15
 * This is a mess and it would be nice to fix it. It has nothing to do with
16
 * __ufunc_api.c
17
 */
18
#define _UMATHMODULE
19
#define _MULTIARRAYMODULE
20
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
21

22
#include "Python.h"
23

24
#include "npy_config.h"
25

26
#include "numpy/arrayobject.h"
27
#include "numpy/ufuncobject.h"
28
#include "numpy/npy_3kcompat.h"
29
#include "abstract.h"
30

31
#include "numpy/npy_math.h"
32
#include "number.h"
33

34
static PyUFuncGenericFunction pyfunc_functions[] = {PyUFunc_On_Om};
35

36
static int
37 1
object_ufunc_type_resolver(PyUFuncObject *ufunc,
38
                                NPY_CASTING casting,
39
                                PyArrayObject **operands,
40
                                PyObject *type_tup,
41
                                PyArray_Descr **out_dtypes)
42
{
43 1
    int i, nop = ufunc->nin + ufunc->nout;
44

45 1
    out_dtypes[0] = PyArray_DescrFromType(NPY_OBJECT);
46 1
    if (out_dtypes[0] == NULL) {
47
        return -1;
48
    }
49

50 1
    for (i = 1; i < nop; ++i) {
51 1
        Py_INCREF(out_dtypes[0]);
52 1
        out_dtypes[i] = out_dtypes[0];
53
    }
54

55
    return 0;
56
}
57

58
static int
59 1
object_ufunc_loop_selector(PyUFuncObject *ufunc,
60
                            PyArray_Descr **NPY_UNUSED(dtypes),
61
                            PyUFuncGenericFunction *out_innerloop,
62
                            void **out_innerloopdata,
63
                            int *out_needs_api)
64
{
65 1
    *out_innerloop = ufunc->functions[0];
66 1
    *out_innerloopdata = ufunc->data[0];
67 1
    *out_needs_api = 1;
68

69 1
    return 0;
70
}
71

72
PyObject *
73 1
ufunc_frompyfunc(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds) {
74 1
    PyObject *function, *pyname = NULL;
75
    int nin, nout, i, nargs;
76
    PyUFunc_PyFuncData *fdata;
77
    PyUFuncObject *self;
78 1
    const char *fname = NULL;
79
    char *str, *types, *doc;
80 1
    Py_ssize_t fname_len = -1;
81
    void * ptr, **data;
82
    int offset[2];
83 1
    PyObject *identity = NULL;  /* note: not the same semantics as Py_None */
84
    static char *kwlist[] = {"", "nin", "nout", "identity", NULL};
85

86 1
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oii|$O:frompyfunc", kwlist,
87
                &function, &nin, &nout, &identity)) {
88
        return NULL;
89
    }
90 1
    if (!PyCallable_Check(function)) {
91 0
        PyErr_SetString(PyExc_TypeError, "function must be callable");
92 0
        return NULL;
93
    }
94

95 1
    nargs = nin + nout;
96

97 1
    pyname = PyObject_GetAttrString(function, "__name__");
98 1
    if (pyname) {
99 1
        fname = PyUnicode_AsUTF8AndSize(pyname, &fname_len);
100
    }
101 1
    if (fname == NULL) {
102 0
        PyErr_Clear();
103 0
        fname = "?";
104 0
        fname_len = 1;
105
    }
106

107
    /*
108
     * ptr will be assigned to self->ptr, holds a pointer for enough memory for
109
     * self->data[0] (fdata)
110
     * self->data
111
     * self->name
112
     * self->types
113
     *
114
     * To be safest, all of these need their memory aligned on void * pointers
115
     * Therefore, we may need to allocate extra space.
116
     */
117 1
    offset[0] = sizeof(PyUFunc_PyFuncData);
118 1
    i = (sizeof(PyUFunc_PyFuncData) % sizeof(void *));
119
    if (i) {
120
        offset[0] += (sizeof(void *) - i);
121
    }
122 1
    offset[1] = nargs;
123 1
    i = (nargs % sizeof(void *));
124 1
    if (i) {
125 1
        offset[1] += (sizeof(void *)-i);
126
    }
127 1
    ptr = PyArray_malloc(offset[0] + offset[1] + sizeof(void *) +
128
                            (fname_len + 14));
129 1
    if (ptr == NULL) {
130 0
        Py_XDECREF(pyname);
131 0
        return PyErr_NoMemory();
132
    }
133 1
    fdata = (PyUFunc_PyFuncData *)(ptr);
134 1
    fdata->callable = function;
135 1
    fdata->nin = nin;
136 1
    fdata->nout = nout;
137

138 1
    data = (void **)(((char *)ptr) + offset[0]);
139 1
    data[0] = (void *)fdata;
140 1
    types = (char *)data + sizeof(void *);
141 1
    for (i = 0; i < nargs; i++) {
142 1
        types[i] = NPY_OBJECT;
143
    }
144 1
    str = types + offset[1];
145 1
    memcpy(str, fname, fname_len);
146 1
    memcpy(str+fname_len, " (vectorized)", 14);
147 1
    Py_XDECREF(pyname);
148

149
    /* Do a better job someday */
150 1
    doc = "dynamic ufunc based on a python function";
151

152 1
    self = (PyUFuncObject *)PyUFunc_FromFuncAndDataAndSignatureAndIdentity(
153
            (PyUFuncGenericFunction *)pyfunc_functions, data,
154
            types, /* ntypes */ 1, nin, nout, identity ? PyUFunc_IdentityValue : PyUFunc_None,
155
            str, doc, /* unused */ 0, NULL, identity);
156

157 1
    if (self == NULL) {
158 1
        PyArray_free(ptr);
159 1
        return NULL;
160
    }
161 1
    Py_INCREF(function);
162 1
    self->obj = function;
163 1
    self->ptr = ptr;
164

165 1
    self->type_resolver = &object_ufunc_type_resolver;
166 1
    self->legacy_inner_loop_selector = &object_ufunc_loop_selector;
167 1
    PyObject_GC_Track(self);
168

169 1
    return (PyObject *)self;
170
}
171

172
/* docstring in numpy.add_newdocs.py */
173
PyObject *
174 1
add_newdoc_ufunc(PyObject *NPY_UNUSED(dummy), PyObject *args)
175
{
176
    PyUFuncObject *ufunc;
177
    PyObject *str;
178 1
    if (!PyArg_ParseTuple(args, "O!O!:_add_newdoc_ufunc", &PyUFunc_Type, &ufunc,
179
                                        &PyUnicode_Type, &str)) {
180
        return NULL;
181
    }
182 1
    if (ufunc->doc != NULL) {
183 1
        PyErr_SetString(PyExc_ValueError,
184
                "Cannot change docstring of ufunc with non-NULL docstring");
185 1
        return NULL;
186
    }
187

188 0
    PyObject *tmp = PyUnicode_AsUTF8String(str);
189 0
    if (tmp == NULL) {
190
        return NULL;
191
    }
192 0
    char *docstr = PyBytes_AS_STRING(tmp);
193

194
    /*
195
     * This introduces a memory leak, as the memory allocated for the doc
196
     * will not be freed even if the ufunc itself is deleted. In practice
197
     * this should not be a problem since the user would have to
198
     * repeatedly create, document, and throw away ufuncs.
199
     */
200 0
    char *newdocstr = malloc(strlen(docstr) + 1);
201 0
    if (!newdocstr) {
202 0
        Py_DECREF(tmp);
203 0
        return PyErr_NoMemory();
204
    }
205 0
    strcpy(newdocstr, docstr);
206 0
    ufunc->doc = newdocstr;
207

208 0
    Py_DECREF(tmp);
209 0
    Py_RETURN_NONE;
210
}
211

212

213
/*
214
 *****************************************************************************
215
 **                            SETUP UFUNCS                                 **
216
 *****************************************************************************
217
 */
218

219
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_out = NULL;
220
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_where = NULL;
221
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_axes = NULL;
222
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_axis = NULL;
223
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_keepdims = NULL;
224
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_casting = NULL;
225
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_order = NULL;
226
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_dtype = NULL;
227
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_subok = NULL;
228
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_signature = NULL;
229
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_sig = NULL;
230
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_extobj = NULL;
231
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_array_prepare = NULL;
232
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_array_wrap = NULL;
233
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_array_finalize = NULL;
234
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_ufunc = NULL;
235
NPY_VISIBILITY_HIDDEN PyObject *npy_um_str_pyvals_name = NULL;
236

237
/* intern some strings used in ufuncs, returns 0 on success */
238
static int
239 1
intern_strings(void)
240
{
241 1
    if (!(npy_um_str_out = PyUnicode_InternFromString("out"))) return -1;
242 1
    if (!(npy_um_str_where = PyUnicode_InternFromString("where"))) return -1;
243 1
    if (!(npy_um_str_axes = PyUnicode_InternFromString("axes"))) return -1;
244 1
    if (!(npy_um_str_axis = PyUnicode_InternFromString("axis"))) return -1;
245 1
    if (!(npy_um_str_keepdims = PyUnicode_InternFromString("keepdims"))) return -1;
246 1
    if (!(npy_um_str_casting = PyUnicode_InternFromString("casting"))) return -1;
247 1
    if (!(npy_um_str_order = PyUnicode_InternFromString("order"))) return -1;
248 1
    if (!(npy_um_str_dtype = PyUnicode_InternFromString("dtype"))) return -1;
249 1
    if (!(npy_um_str_subok = PyUnicode_InternFromString("subok"))) return -1;
250 1
    if (!(npy_um_str_signature = PyUnicode_InternFromString("signature"))) return -1;
251 1
    if (!(npy_um_str_sig = PyUnicode_InternFromString("sig"))) return -1;
252 1
    if (!(npy_um_str_extobj = PyUnicode_InternFromString("extobj"))) return -1;
253 1
    if (!(npy_um_str_array_prepare = PyUnicode_InternFromString("__array_prepare__"))) return -1;
254 1
    if (!(npy_um_str_array_wrap = PyUnicode_InternFromString("__array_wrap__"))) return -1;
255 1
    if (!(npy_um_str_array_finalize = PyUnicode_InternFromString("__array_finalize__"))) return -1;
256 1
    if (!(npy_um_str_ufunc = PyUnicode_InternFromString("__array_ufunc__"))) return -1;
257 1
    if (!(npy_um_str_pyvals_name = PyUnicode_InternFromString(UFUNC_PYVALS_NAME))) return -1;
258 1
    return 0;
259
}
260

261
/* Setup the umath part of the module */
262

263 1
int initumath(PyObject *m)
264
{
265
    PyObject *d, *s, *s2;
266 1
    int UFUNC_FLOATING_POINT_SUPPORT = 1;
267

268
#ifdef NO_UFUNC_FLOATING_POINT_SUPPORT
269
    UFUNC_FLOATING_POINT_SUPPORT = 0;
270
#endif
271

272
    /* Add some symbolic constants to the module */
273 1
    d = PyModule_GetDict(m);
274

275 1
    PyDict_SetItemString(d, "pi", s = PyFloat_FromDouble(NPY_PI));
276 1
    Py_DECREF(s);
277 1
    PyDict_SetItemString(d, "e", s = PyFloat_FromDouble(NPY_E));
278 1
    Py_DECREF(s);
279 1
    PyDict_SetItemString(d, "euler_gamma", s = PyFloat_FromDouble(NPY_EULER));
280 1
    Py_DECREF(s);
281

282
#define ADDCONST(str) PyModule_AddIntConstant(m, #str, UFUNC_##str)
283
#define ADDSCONST(str) PyModule_AddStringConstant(m, "UFUNC_" #str, UFUNC_##str)
284

285 1
    ADDCONST(ERR_IGNORE);
286 1
    ADDCONST(ERR_WARN);
287 1
    ADDCONST(ERR_CALL);
288 1
    ADDCONST(ERR_RAISE);
289 1
    ADDCONST(ERR_PRINT);
290 1
    ADDCONST(ERR_LOG);
291 1
    ADDCONST(ERR_DEFAULT);
292

293 1
    ADDCONST(SHIFT_DIVIDEBYZERO);
294 1
    ADDCONST(SHIFT_OVERFLOW);
295 1
    ADDCONST(SHIFT_UNDERFLOW);
296 1
    ADDCONST(SHIFT_INVALID);
297

298 1
    ADDCONST(FPE_DIVIDEBYZERO);
299 1
    ADDCONST(FPE_OVERFLOW);
300 1
    ADDCONST(FPE_UNDERFLOW);
301 1
    ADDCONST(FPE_INVALID);
302

303 1
    ADDCONST(FLOATING_POINT_SUPPORT);
304

305 1
    ADDSCONST(PYVALS_NAME);
306

307
#undef ADDCONST
308
#undef ADDSCONST
309 1
    PyModule_AddIntConstant(m, "UFUNC_BUFSIZE_DEFAULT", (long)NPY_BUFSIZE);
310

311 1
    PyModule_AddObject(m, "PINF", PyFloat_FromDouble(NPY_INFINITY));
312 1
    PyModule_AddObject(m, "NINF", PyFloat_FromDouble(-NPY_INFINITY));
313 1
    PyModule_AddObject(m, "PZERO", PyFloat_FromDouble(NPY_PZERO));
314 1
    PyModule_AddObject(m, "NZERO", PyFloat_FromDouble(NPY_NZERO));
315 1
    PyModule_AddObject(m, "NAN", PyFloat_FromDouble(NPY_NAN));
316

317 1
    s = PyDict_GetItemString(d, "true_divide");
318 1
    PyDict_SetItemString(d, "divide", s);
319

320 1
    s = PyDict_GetItemString(d, "conjugate");
321 1
    s2 = PyDict_GetItemString(d, "remainder");
322
    /* Setup the array object's numerical structures with appropriate
323
       ufuncs in d*/
324 1
    _PyArray_SetNumericOps(d);
325

326 1
    PyDict_SetItemString(d, "conj", s);
327 1
    PyDict_SetItemString(d, "mod", s2);
328

329 1
    if (intern_strings() < 0) {
330 0
        PyErr_SetString(PyExc_RuntimeError,
331
           "cannot intern umath strings while initializing _multiarray_umath.");
332 0
        return -1;
333
    }
334

335
    return 0;
336
}

Read our documentation on viewing source code .

Loading