numexpr 2.10.2__cp313-cp313-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- numexpr/__init__.py +66 -0
- numexpr/complex_functions.hpp +427 -0
- numexpr/cpuinfo.py +859 -0
- numexpr/expressions.py +523 -0
- numexpr/functions.hpp +140 -0
- numexpr/interp_body.cpp +543 -0
- numexpr/interpreter.cp313-win32.pyd +0 -0
- numexpr/interpreter.cpp +1528 -0
- numexpr/interpreter.hpp +107 -0
- numexpr/missing_posix_functions.hpp +102 -0
- numexpr/module.cpp +537 -0
- numexpr/module.hpp +60 -0
- numexpr/msvc_function_stubs.hpp +150 -0
- numexpr/necompiler.py +1005 -0
- numexpr/numexpr_config.hpp +51 -0
- numexpr/numexpr_object.cpp +408 -0
- numexpr/numexpr_object.hpp +34 -0
- numexpr/opcodes.hpp +179 -0
- numexpr/str-two-way.hpp +435 -0
- numexpr/tests/__init__.py +14 -0
- numexpr/tests/test_numexpr.py +1421 -0
- numexpr/utils.py +309 -0
- numexpr/version.py +5 -0
- numexpr/win32/pthread.c +218 -0
- numexpr/win32/pthread.h +119 -0
- numexpr/win32/stdint.h +235 -0
- numexpr-2.10.2.dist-info/AUTHORS.txt +31 -0
- numexpr-2.10.2.dist-info/LICENSE.txt +21 -0
- numexpr-2.10.2.dist-info/METADATA +214 -0
- numexpr-2.10.2.dist-info/RECORD +32 -0
- numexpr-2.10.2.dist-info/WHEEL +5 -0
- numexpr-2.10.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#ifndef NUMEXPR_CONFIG_HPP
|
|
2
|
+
#define NUMEXPR_CONFIG_HPP
|
|
3
|
+
|
|
4
|
+
// x86 platform works with unaligned reads and writes
|
|
5
|
+
// MW: I have seen exceptions to this when the compiler chooses to use aligned SSE
|
|
6
|
+
#if (defined(NPY_CPU_X86) || defined(NPY_CPU_AMD64))
|
|
7
|
+
# define USE_UNALIGNED_ACCESS 1
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
// #ifdef SCIPY_MKL_H
|
|
11
|
+
// #define USE_VML
|
|
12
|
+
// #endif
|
|
13
|
+
|
|
14
|
+
#ifdef USE_VML
|
|
15
|
+
/* The values below have been tuned for a Skylake processor (E3-1245 v5 @ 3.50GHz) */
|
|
16
|
+
#define BLOCK_SIZE1 1024
|
|
17
|
+
#else
|
|
18
|
+
/* The values below have been tuned for a Skylake processor (E3-1245 v5 @ 3.50GHz) */
|
|
19
|
+
#define BLOCK_SIZE1 1024
|
|
20
|
+
#endif
|
|
21
|
+
|
|
22
|
+
// The default threadpool size. It's prefer that the user set this via an
|
|
23
|
+
// environment variable, "NUMEXPR_MAX_THREADS"
|
|
24
|
+
#define DEFAULT_MAX_THREADS 64
|
|
25
|
+
|
|
26
|
+
// Remove dependence on NPY_MAXARGS, which would be a runtime constant instead of compiletime
|
|
27
|
+
// constant. If numpy raises NPY_MAXARGS, we should notice and raise this as well
|
|
28
|
+
#define NE_MAXARGS 64
|
|
29
|
+
|
|
30
|
+
#if defined(_WIN32)
|
|
31
|
+
#include "win32/pthread.h"
|
|
32
|
+
#include <process.h>
|
|
33
|
+
#define getpid _getpid
|
|
34
|
+
#else
|
|
35
|
+
#include <pthread.h>
|
|
36
|
+
#include "unistd.h"
|
|
37
|
+
#endif
|
|
38
|
+
|
|
39
|
+
#ifdef USE_VML
|
|
40
|
+
#include "mkl_vml.h"
|
|
41
|
+
#include "mkl_service.h"
|
|
42
|
+
#endif
|
|
43
|
+
|
|
44
|
+
#ifdef _WIN32
|
|
45
|
+
#ifndef __MINGW32__
|
|
46
|
+
#include "missing_posix_functions.hpp"
|
|
47
|
+
#endif
|
|
48
|
+
#include "msvc_function_stubs.hpp"
|
|
49
|
+
#endif
|
|
50
|
+
|
|
51
|
+
#endif // NUMEXPR_CONFIG_HPP
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
/*********************************************************************
|
|
2
|
+
Numexpr - Fast numerical array expression evaluator for NumPy.
|
|
3
|
+
|
|
4
|
+
License: MIT
|
|
5
|
+
Author: See AUTHORS.txt
|
|
6
|
+
|
|
7
|
+
See LICENSE.txt for details about copyright and rights to use.
|
|
8
|
+
**********************************************************************/
|
|
9
|
+
|
|
10
|
+
#include "module.hpp"
|
|
11
|
+
#include <structmember.h>
|
|
12
|
+
|
|
13
|
+
#include "numexpr_config.hpp"
|
|
14
|
+
#include "interpreter.hpp"
|
|
15
|
+
#include "numexpr_object.hpp"
|
|
16
|
+
|
|
17
|
+
static int
|
|
18
|
+
size_from_char(char c)
|
|
19
|
+
{
|
|
20
|
+
switch (c) {
|
|
21
|
+
case 'b': return sizeof(char);
|
|
22
|
+
case 'i': return sizeof(int);
|
|
23
|
+
case 'l': return sizeof(long long);
|
|
24
|
+
case 'f': return sizeof(float);
|
|
25
|
+
case 'd': return sizeof(double);
|
|
26
|
+
case 'c': return 2*sizeof(double);
|
|
27
|
+
case 's': return 0; /* strings are ok but size must be computed */
|
|
28
|
+
default:
|
|
29
|
+
PyErr_SetString(PyExc_TypeError, "signature value not in 'bilfdcs'");
|
|
30
|
+
return -1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static void
|
|
35
|
+
NumExpr_dealloc(NumExprObject *self)
|
|
36
|
+
{
|
|
37
|
+
Py_XDECREF(self->signature);
|
|
38
|
+
Py_XDECREF(self->tempsig);
|
|
39
|
+
Py_XDECREF(self->constsig);
|
|
40
|
+
Py_XDECREF(self->fullsig);
|
|
41
|
+
Py_XDECREF(self->program);
|
|
42
|
+
Py_XDECREF(self->constants);
|
|
43
|
+
Py_XDECREF(self->input_names);
|
|
44
|
+
PyMem_Del(self->mem);
|
|
45
|
+
PyMem_Del(self->rawmem);
|
|
46
|
+
PyMem_Del(self->memsteps);
|
|
47
|
+
PyMem_Del(self->memsizes);
|
|
48
|
+
Py_TYPE(self)->tp_free((PyObject*)self);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static PyObject *
|
|
52
|
+
NumExpr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
53
|
+
{
|
|
54
|
+
NumExprObject *self = (NumExprObject *)type->tp_alloc(type, 0);
|
|
55
|
+
if (self != NULL) {
|
|
56
|
+
#define INIT_WITH(name, object) \
|
|
57
|
+
self->name = object; \
|
|
58
|
+
if (!self->name) { \
|
|
59
|
+
Py_DECREF(self); \
|
|
60
|
+
return NULL; \
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
INIT_WITH(signature, PyBytes_FromString(""));
|
|
64
|
+
INIT_WITH(tempsig, PyBytes_FromString(""));
|
|
65
|
+
INIT_WITH(constsig, PyBytes_FromString(""));
|
|
66
|
+
INIT_WITH(fullsig, PyBytes_FromString(""));
|
|
67
|
+
INIT_WITH(program, PyBytes_FromString(""));
|
|
68
|
+
INIT_WITH(constants, PyTuple_New(0));
|
|
69
|
+
Py_INCREF(Py_None);
|
|
70
|
+
self->input_names = Py_None;
|
|
71
|
+
self->mem = NULL;
|
|
72
|
+
self->rawmem = NULL;
|
|
73
|
+
self->memsteps = NULL;
|
|
74
|
+
self->memsizes = NULL;
|
|
75
|
+
self->rawmemsize = 0;
|
|
76
|
+
self->n_inputs = 0;
|
|
77
|
+
self->n_constants = 0;
|
|
78
|
+
self->n_temps = 0;
|
|
79
|
+
#undef INIT_WITH
|
|
80
|
+
}
|
|
81
|
+
return (PyObject *)self;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
#define CHARP(s) ((char *)(s))
|
|
85
|
+
|
|
86
|
+
static int
|
|
87
|
+
NumExpr_init(NumExprObject *self, PyObject *args, PyObject *kwds)
|
|
88
|
+
{
|
|
89
|
+
int i, j, mem_offset;
|
|
90
|
+
int n_inputs, n_constants, n_temps;
|
|
91
|
+
PyObject *signature = NULL, *tempsig = NULL, *constsig = NULL;
|
|
92
|
+
PyObject *fullsig = NULL, *program = NULL, *constants = NULL;
|
|
93
|
+
PyObject *input_names = NULL, *o_constants = NULL;
|
|
94
|
+
int *itemsizes = NULL;
|
|
95
|
+
char **mem = NULL, *rawmem = NULL;
|
|
96
|
+
npy_intp *memsteps;
|
|
97
|
+
npy_intp *memsizes;
|
|
98
|
+
int rawmemsize;
|
|
99
|
+
static char *kwlist[] = {CHARP("signature"), CHARP("tempsig"),
|
|
100
|
+
CHARP("program"), CHARP("constants"),
|
|
101
|
+
CHARP("input_names"), NULL};
|
|
102
|
+
|
|
103
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "SSS|OO", kwlist,
|
|
104
|
+
&signature,
|
|
105
|
+
&tempsig,
|
|
106
|
+
&program, &o_constants,
|
|
107
|
+
&input_names)) {
|
|
108
|
+
return -1;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
n_inputs = (int)PyBytes_Size(signature);
|
|
112
|
+
n_temps = (int)PyBytes_Size(tempsig);
|
|
113
|
+
|
|
114
|
+
if (o_constants) {
|
|
115
|
+
if (!PySequence_Check(o_constants) ) {
|
|
116
|
+
PyErr_SetString(PyExc_TypeError, "constants must be a sequence");
|
|
117
|
+
return -1;
|
|
118
|
+
}
|
|
119
|
+
n_constants = (int)PySequence_Length(o_constants);
|
|
120
|
+
if (!(constants = PyTuple_New(n_constants)))
|
|
121
|
+
return -1;
|
|
122
|
+
if (!(constsig = PyBytes_FromStringAndSize(NULL, n_constants))) {
|
|
123
|
+
Py_DECREF(constants);
|
|
124
|
+
return -1;
|
|
125
|
+
}
|
|
126
|
+
if (!(itemsizes = PyMem_New(int, n_constants))) {
|
|
127
|
+
Py_DECREF(constants);
|
|
128
|
+
return -1;
|
|
129
|
+
}
|
|
130
|
+
for (i = 0; i < n_constants; i++) {
|
|
131
|
+
PyObject *o;
|
|
132
|
+
if (!(o = PySequence_GetItem(o_constants, i))) { /* new reference */
|
|
133
|
+
Py_DECREF(constants);
|
|
134
|
+
Py_DECREF(constsig);
|
|
135
|
+
PyMem_Del(itemsizes);
|
|
136
|
+
return -1;
|
|
137
|
+
}
|
|
138
|
+
PyTuple_SET_ITEM(constants, i, o); /* steals reference */
|
|
139
|
+
if (PyBool_Check(o)) {
|
|
140
|
+
PyBytes_AS_STRING(constsig)[i] = 'b';
|
|
141
|
+
itemsizes[i] = size_from_char('b');
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (PyArray_IsScalar(o, Int32)) {
|
|
146
|
+
PyBytes_AS_STRING(constsig)[i] = 'i';
|
|
147
|
+
itemsizes[i] = size_from_char('i');
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (PyArray_IsScalar(o, Int64)) {
|
|
152
|
+
PyBytes_AS_STRING(constsig)[i] = 'l';
|
|
153
|
+
itemsizes[i] = size_from_char('l');
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
/* The Float32 scalars are the only ones that should reach here */
|
|
157
|
+
if (PyArray_IsScalar(o, Float32)) {
|
|
158
|
+
PyBytes_AS_STRING(constsig)[i] = 'f';
|
|
159
|
+
itemsizes[i] = size_from_char('f');
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (PyFloat_Check(o)) {
|
|
163
|
+
/* Python float constants are double precision by default */
|
|
164
|
+
PyBytes_AS_STRING(constsig)[i] = 'd';
|
|
165
|
+
itemsizes[i] = size_from_char('d');
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (PyComplex_Check(o)) {
|
|
169
|
+
PyBytes_AS_STRING(constsig)[i] = 'c';
|
|
170
|
+
itemsizes[i] = size_from_char('c');
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (PyBytes_Check(o)) {
|
|
174
|
+
PyBytes_AS_STRING(constsig)[i] = 's';
|
|
175
|
+
itemsizes[i] = (int)PyBytes_GET_SIZE(o);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
PyErr_SetString(PyExc_TypeError, "constants must be of type bool/int/long/float/double/complex/bytes");
|
|
179
|
+
Py_DECREF(constsig);
|
|
180
|
+
Py_DECREF(constants);
|
|
181
|
+
PyMem_Del(itemsizes);
|
|
182
|
+
return -1;
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
n_constants = 0;
|
|
186
|
+
if (!(constants = PyTuple_New(0)))
|
|
187
|
+
return -1;
|
|
188
|
+
if (!(constsig = PyBytes_FromString(""))) {
|
|
189
|
+
Py_DECREF(constants);
|
|
190
|
+
return -1;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
fullsig = PyBytes_FromFormat("%c%s%s%s", get_return_sig(program),
|
|
195
|
+
PyBytes_AS_STRING(signature), PyBytes_AS_STRING(constsig),
|
|
196
|
+
PyBytes_AS_STRING(tempsig));
|
|
197
|
+
if (!fullsig) {
|
|
198
|
+
Py_DECREF(constants);
|
|
199
|
+
Py_DECREF(constsig);
|
|
200
|
+
PyMem_Del(itemsizes);
|
|
201
|
+
return -1;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (!input_names) {
|
|
205
|
+
input_names = Py_None;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* Compute the size of registers. We leave temps out (will be
|
|
209
|
+
malloc'ed later on). */
|
|
210
|
+
rawmemsize = 0;
|
|
211
|
+
for (i = 0; i < n_constants; i++)
|
|
212
|
+
rawmemsize += itemsizes[i];
|
|
213
|
+
rawmemsize *= BLOCK_SIZE1;
|
|
214
|
+
|
|
215
|
+
mem = PyMem_New(char *, 1 + n_inputs + n_constants + n_temps);
|
|
216
|
+
rawmem = PyMem_New(char, rawmemsize);
|
|
217
|
+
memsteps = PyMem_New(npy_intp, 1 + n_inputs + n_constants + n_temps);
|
|
218
|
+
memsizes = PyMem_New(npy_intp, 1 + n_inputs + n_constants + n_temps);
|
|
219
|
+
if (!mem || !rawmem || !memsteps || !memsizes) {
|
|
220
|
+
Py_DECREF(constants);
|
|
221
|
+
Py_DECREF(constsig);
|
|
222
|
+
Py_DECREF(fullsig);
|
|
223
|
+
PyMem_Del(itemsizes);
|
|
224
|
+
PyMem_Del(mem);
|
|
225
|
+
PyMem_Del(rawmem);
|
|
226
|
+
PyMem_Del(memsteps);
|
|
227
|
+
PyMem_Del(memsizes);
|
|
228
|
+
return -1;
|
|
229
|
+
}
|
|
230
|
+
/*
|
|
231
|
+
0 -> output
|
|
232
|
+
[1, n_inputs+1) -> inputs
|
|
233
|
+
[n_inputs+1, n_inputs+n_consts+1) -> constants
|
|
234
|
+
[n_inputs+n_consts+1, n_inputs+n_consts+n_temps+1) -> temps
|
|
235
|
+
*/
|
|
236
|
+
/* Fill in 'mem' and 'rawmem' for constants */
|
|
237
|
+
mem_offset = 0;
|
|
238
|
+
for (i = 0; i < n_constants; i++) {
|
|
239
|
+
char c = PyBytes_AS_STRING(constsig)[i];
|
|
240
|
+
int size = itemsizes[i];
|
|
241
|
+
mem[i+n_inputs+1] = rawmem + mem_offset;
|
|
242
|
+
mem_offset += BLOCK_SIZE1 * size;
|
|
243
|
+
memsteps[i+n_inputs+1] = memsizes[i+n_inputs+1] = size;
|
|
244
|
+
/* fill in the constants */
|
|
245
|
+
if (c == 'b') {
|
|
246
|
+
char *bmem = (char*)mem[i+n_inputs+1];
|
|
247
|
+
char value = (char)PyLong_AsLong(PyTuple_GET_ITEM(constants, i));
|
|
248
|
+
for (j = 0; j < BLOCK_SIZE1; j++) {
|
|
249
|
+
bmem[j] = value;
|
|
250
|
+
}
|
|
251
|
+
} else if (c == 'i') {
|
|
252
|
+
int *imem = (int*)mem[i+n_inputs+1];
|
|
253
|
+
int value = (int)PyLong_AsLong(PyTuple_GET_ITEM(constants, i));
|
|
254
|
+
for (j = 0; j < BLOCK_SIZE1; j++) {
|
|
255
|
+
imem[j] = value;
|
|
256
|
+
}
|
|
257
|
+
} else if (c == 'l') {
|
|
258
|
+
long long *lmem = (long long*)mem[i+n_inputs+1];
|
|
259
|
+
long long value = PyLong_AsLongLong(PyTuple_GET_ITEM(constants, i));
|
|
260
|
+
for (j = 0; j < BLOCK_SIZE1; j++) {
|
|
261
|
+
lmem[j] = value;
|
|
262
|
+
}
|
|
263
|
+
} else if (c == 'f') {
|
|
264
|
+
/* In this particular case the constant is in a NumPy scalar
|
|
265
|
+
and in a regular Python object */
|
|
266
|
+
float *fmem = (float*)mem[i+n_inputs+1];
|
|
267
|
+
float value = PyArrayScalar_VAL(PyTuple_GET_ITEM(constants, i),
|
|
268
|
+
Float);
|
|
269
|
+
for (j = 0; j < BLOCK_SIZE1; j++) {
|
|
270
|
+
fmem[j] = value;
|
|
271
|
+
}
|
|
272
|
+
} else if (c == 'd') {
|
|
273
|
+
double *dmem = (double*)mem[i+n_inputs+1];
|
|
274
|
+
double value = PyFloat_AS_DOUBLE(PyTuple_GET_ITEM(constants, i));
|
|
275
|
+
for (j = 0; j < BLOCK_SIZE1; j++) {
|
|
276
|
+
dmem[j] = value;
|
|
277
|
+
}
|
|
278
|
+
} else if (c == 'c') {
|
|
279
|
+
double *cmem = (double*)mem[i+n_inputs+1];
|
|
280
|
+
Py_complex value = PyComplex_AsCComplex(PyTuple_GET_ITEM(constants, i));
|
|
281
|
+
for (j = 0; j < 2*BLOCK_SIZE1; j+=2) {
|
|
282
|
+
cmem[j] = value.real;
|
|
283
|
+
cmem[j+1] = value.imag;
|
|
284
|
+
}
|
|
285
|
+
} else if (c == 's') {
|
|
286
|
+
char *smem = (char*)mem[i+n_inputs+1];
|
|
287
|
+
char *value = PyBytes_AS_STRING(PyTuple_GET_ITEM(constants, i));
|
|
288
|
+
for (j = 0; j < size*BLOCK_SIZE1; j+=size) {
|
|
289
|
+
memcpy(smem + j, value, size);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/* This is no longer needed since no unusual item sizes appear
|
|
294
|
+
in temporaries (there are no string temporaries). */
|
|
295
|
+
PyMem_Del(itemsizes);
|
|
296
|
+
|
|
297
|
+
/* Fill in 'memsteps' and 'memsizes' for temps */
|
|
298
|
+
for (i = 0; i < n_temps; i++) {
|
|
299
|
+
char c = PyBytes_AS_STRING(tempsig)[i];
|
|
300
|
+
int size = size_from_char(c);
|
|
301
|
+
memsteps[i+n_inputs+n_constants+1] = size;
|
|
302
|
+
memsizes[i+n_inputs+n_constants+1] = size;
|
|
303
|
+
}
|
|
304
|
+
/* See if any errors occured (e.g., in size_from_char) or if mem_offset is wrong */
|
|
305
|
+
if (PyErr_Occurred() || mem_offset != rawmemsize) {
|
|
306
|
+
if (mem_offset != rawmemsize) {
|
|
307
|
+
PyErr_Format(PyExc_RuntimeError, "mem_offset does not match rawmemsize");
|
|
308
|
+
}
|
|
309
|
+
Py_DECREF(constants);
|
|
310
|
+
Py_DECREF(constsig);
|
|
311
|
+
Py_DECREF(fullsig);
|
|
312
|
+
PyMem_Del(mem);
|
|
313
|
+
PyMem_Del(rawmem);
|
|
314
|
+
PyMem_Del(memsteps);
|
|
315
|
+
PyMem_Del(memsizes);
|
|
316
|
+
return -1;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
#define REPLACE_OBJ(arg) \
|
|
321
|
+
{PyObject *tmp = self->arg; \
|
|
322
|
+
self->arg = arg; \
|
|
323
|
+
Py_XDECREF(tmp);}
|
|
324
|
+
#define INCREF_REPLACE_OBJ(arg) {Py_INCREF(arg); REPLACE_OBJ(arg);}
|
|
325
|
+
#define REPLACE_MEM(arg) {PyMem_Del(self->arg); self->arg=arg;}
|
|
326
|
+
|
|
327
|
+
INCREF_REPLACE_OBJ(signature);
|
|
328
|
+
INCREF_REPLACE_OBJ(tempsig);
|
|
329
|
+
REPLACE_OBJ(constsig);
|
|
330
|
+
REPLACE_OBJ(fullsig);
|
|
331
|
+
INCREF_REPLACE_OBJ(program);
|
|
332
|
+
REPLACE_OBJ(constants);
|
|
333
|
+
INCREF_REPLACE_OBJ(input_names);
|
|
334
|
+
REPLACE_MEM(mem);
|
|
335
|
+
REPLACE_MEM(rawmem);
|
|
336
|
+
REPLACE_MEM(memsteps);
|
|
337
|
+
REPLACE_MEM(memsizes);
|
|
338
|
+
self->rawmemsize = rawmemsize;
|
|
339
|
+
self->n_inputs = n_inputs;
|
|
340
|
+
self->n_constants = n_constants;
|
|
341
|
+
self->n_temps = n_temps;
|
|
342
|
+
|
|
343
|
+
#undef REPLACE_OBJ
|
|
344
|
+
#undef INCREF_REPLACE_OBJ
|
|
345
|
+
#undef REPLACE_MEM
|
|
346
|
+
|
|
347
|
+
return check_program(self);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
static PyMethodDef NumExpr_methods[] = {
|
|
351
|
+
{"run", (PyCFunction) NumExpr_run, METH_VARARGS|METH_KEYWORDS, NULL},
|
|
352
|
+
{NULL, NULL}
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
static PyMemberDef NumExpr_members[] = {
|
|
356
|
+
{CHARP("signature"), T_OBJECT_EX, offsetof(NumExprObject, signature), READONLY, NULL},
|
|
357
|
+
{CHARP("constsig"), T_OBJECT_EX, offsetof(NumExprObject, constsig), READONLY, NULL},
|
|
358
|
+
{CHARP("tempsig"), T_OBJECT_EX, offsetof(NumExprObject, tempsig), READONLY, NULL},
|
|
359
|
+
{CHARP("fullsig"), T_OBJECT_EX, offsetof(NumExprObject, fullsig), READONLY, NULL},
|
|
360
|
+
|
|
361
|
+
{CHARP("program"), T_OBJECT_EX, offsetof(NumExprObject, program), READONLY, NULL},
|
|
362
|
+
{CHARP("constants"), T_OBJECT_EX, offsetof(NumExprObject, constants),
|
|
363
|
+
READONLY, NULL},
|
|
364
|
+
{CHARP("input_names"), T_OBJECT, offsetof(NumExprObject, input_names), 0, NULL},
|
|
365
|
+
{NULL},
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
PyTypeObject NumExprType = {
|
|
369
|
+
PyVarObject_HEAD_INIT(NULL, 0)
|
|
370
|
+
"numexpr.NumExpr", /*tp_name*/
|
|
371
|
+
sizeof(NumExprObject), /*tp_basicsize*/
|
|
372
|
+
0, /*tp_itemsize*/
|
|
373
|
+
(destructor)NumExpr_dealloc, /*tp_dealloc*/
|
|
374
|
+
0, /*tp_print*/
|
|
375
|
+
0, /*tp_getattr*/
|
|
376
|
+
0, /*tp_setattr*/
|
|
377
|
+
0, /*tp_compare*/
|
|
378
|
+
0, /*tp_repr*/
|
|
379
|
+
0, /*tp_as_number*/
|
|
380
|
+
0, /*tp_as_sequence*/
|
|
381
|
+
0, /*tp_as_mapping*/
|
|
382
|
+
0, /*tp_hash */
|
|
383
|
+
(ternaryfunc)NumExpr_run, /*tp_call*/
|
|
384
|
+
0, /*tp_str*/
|
|
385
|
+
0, /*tp_getattro*/
|
|
386
|
+
0, /*tp_setattro*/
|
|
387
|
+
0, /*tp_as_buffer*/
|
|
388
|
+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
|
389
|
+
"NumExpr objects", /* tp_doc */
|
|
390
|
+
0, /* tp_traverse */
|
|
391
|
+
0, /* tp_clear */
|
|
392
|
+
0, /* tp_richcompare */
|
|
393
|
+
0, /* tp_weaklistoffset */
|
|
394
|
+
0, /* tp_iter */
|
|
395
|
+
0, /* tp_iternext */
|
|
396
|
+
NumExpr_methods, /* tp_methods */
|
|
397
|
+
NumExpr_members, /* tp_members */
|
|
398
|
+
0, /* tp_getset */
|
|
399
|
+
0, /* tp_base */
|
|
400
|
+
0, /* tp_dict */
|
|
401
|
+
0, /* tp_descr_get */
|
|
402
|
+
0, /* tp_descr_set */
|
|
403
|
+
0, /* tp_dictoffset */
|
|
404
|
+
(initproc)NumExpr_init, /* tp_init */
|
|
405
|
+
0, /* tp_alloc */
|
|
406
|
+
NumExpr_new, /* tp_new */
|
|
407
|
+
};
|
|
408
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#ifndef NUMEXPR_OBJECT_HPP
|
|
2
|
+
#define NUMEXPR_OBJECT_HPP
|
|
3
|
+
/*********************************************************************
|
|
4
|
+
Numexpr - Fast numerical array expression evaluator for NumPy.
|
|
5
|
+
|
|
6
|
+
License: MIT
|
|
7
|
+
Author: See AUTHORS.txt
|
|
8
|
+
|
|
9
|
+
See LICENSE.txt for details about copyright and rights to use.
|
|
10
|
+
**********************************************************************/
|
|
11
|
+
|
|
12
|
+
struct NumExprObject
|
|
13
|
+
{
|
|
14
|
+
PyObject_HEAD
|
|
15
|
+
PyObject *signature; /* a python string */
|
|
16
|
+
PyObject *tempsig;
|
|
17
|
+
PyObject *constsig;
|
|
18
|
+
PyObject *fullsig;
|
|
19
|
+
PyObject *program; /* a python string */
|
|
20
|
+
PyObject *constants; /* a tuple of int/float/complex */
|
|
21
|
+
PyObject *input_names; /* tuple of strings */
|
|
22
|
+
char **mem; /* pointers to registers */
|
|
23
|
+
char *rawmem; /* a chunks of raw memory for storing registers */
|
|
24
|
+
npy_intp *memsteps;
|
|
25
|
+
npy_intp *memsizes;
|
|
26
|
+
int rawmemsize;
|
|
27
|
+
int n_inputs;
|
|
28
|
+
int n_constants;
|
|
29
|
+
int n_temps;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
extern PyTypeObject NumExprType;
|
|
33
|
+
|
|
34
|
+
#endif // NUMEXPR_OBJECT_HPP
|
numexpr/opcodes.hpp
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/*********************************************************************
|
|
2
|
+
Numexpr - Fast numerical array expression evaluator for NumPy.
|
|
3
|
+
|
|
4
|
+
License: MIT
|
|
5
|
+
Author: See AUTHORS.txt
|
|
6
|
+
|
|
7
|
+
See LICENSE.txt for details about copyright and rights to use.
|
|
8
|
+
**********************************************************************/
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
OPCODE(n, enum_name, exported, return_type, arg1_type, arg2_type, arg3_type)
|
|
12
|
+
|
|
13
|
+
`exported` is NULL if the opcode shouldn't exported by the Python module.
|
|
14
|
+
|
|
15
|
+
Types are Tb, Ti, Tl, Tf, Td, Tc, Ts, Tn, and T0; these symbols should be
|
|
16
|
+
#defined to whatever is needed. (T0 is the no-such-arg type.)
|
|
17
|
+
|
|
18
|
+
*/
|
|
19
|
+
OPCODE(0, OP_NOOP, "noop", T0, T0, T0, T0)
|
|
20
|
+
|
|
21
|
+
OPCODE(1, OP_COPY_BB, "copy_bb", Tb, Tb, T0, T0)
|
|
22
|
+
|
|
23
|
+
OPCODE(2, OP_INVERT_BB, "invert_bb", Tb, Tb, T0, T0)
|
|
24
|
+
OPCODE(3, OP_AND_BBB, "and_bbb", Tb, Tb, Tb, T0)
|
|
25
|
+
OPCODE(4, OP_OR_BBB, "or_bbb", Tb, Tb, Tb, T0)
|
|
26
|
+
|
|
27
|
+
OPCODE(5, OP_EQ_BBB, "eq_bbb", Tb, Tb, Tb, T0)
|
|
28
|
+
OPCODE(6, OP_NE_BBB, "ne_bbb", Tb, Tb, Tb, T0)
|
|
29
|
+
|
|
30
|
+
OPCODE(7, OP_GT_BII, "gt_bii", Tb, Ti, Ti, T0)
|
|
31
|
+
OPCODE(8, OP_GE_BII, "ge_bii", Tb, Ti, Ti, T0)
|
|
32
|
+
OPCODE(9, OP_EQ_BII, "eq_bii", Tb, Ti, Ti, T0)
|
|
33
|
+
OPCODE(10, OP_NE_BII, "ne_bii", Tb, Ti, Ti, T0)
|
|
34
|
+
|
|
35
|
+
OPCODE(11, OP_GT_BLL, "gt_bll", Tb, Tl, Tl, T0)
|
|
36
|
+
OPCODE(12, OP_GE_BLL, "ge_bll", Tb, Tl, Tl, T0)
|
|
37
|
+
OPCODE(13, OP_EQ_BLL, "eq_bll", Tb, Tl, Tl, T0)
|
|
38
|
+
OPCODE(14, OP_NE_BLL, "ne_bll", Tb, Tl, Tl, T0)
|
|
39
|
+
|
|
40
|
+
OPCODE(15, OP_GT_BFF, "gt_bff", Tb, Tf, Tf, T0)
|
|
41
|
+
OPCODE(16, OP_GE_BFF, "ge_bff", Tb, Tf, Tf, T0)
|
|
42
|
+
OPCODE(17, OP_EQ_BFF, "eq_bff", Tb, Tf, Tf, T0)
|
|
43
|
+
OPCODE(18, OP_NE_BFF, "ne_bff", Tb, Tf, Tf, T0)
|
|
44
|
+
|
|
45
|
+
OPCODE(19, OP_GT_BDD, "gt_bdd", Tb, Td, Td, T0)
|
|
46
|
+
OPCODE(20, OP_GE_BDD, "ge_bdd", Tb, Td, Td, T0)
|
|
47
|
+
OPCODE(21, OP_EQ_BDD, "eq_bdd", Tb, Td, Td, T0)
|
|
48
|
+
OPCODE(22, OP_NE_BDD, "ne_bdd", Tb, Td, Td, T0)
|
|
49
|
+
|
|
50
|
+
OPCODE(23, OP_GT_BSS, "gt_bss", Tb, Ts, Ts, T0)
|
|
51
|
+
OPCODE(24, OP_GE_BSS, "ge_bss", Tb, Ts, Ts, T0)
|
|
52
|
+
OPCODE(25, OP_EQ_BSS, "eq_bss", Tb, Ts, Ts, T0)
|
|
53
|
+
OPCODE(26, OP_NE_BSS, "ne_bss", Tb, Ts, Ts, T0)
|
|
54
|
+
|
|
55
|
+
OPCODE(27, OP_CAST_IB, "cast_ib", Ti, Tb, T0, T0)
|
|
56
|
+
OPCODE(28, OP_COPY_II, "copy_ii", Ti, Ti, T0, T0)
|
|
57
|
+
OPCODE(29, OP_ONES_LIKE_II, "ones_like_ii", Ti, T0, T0, T0)
|
|
58
|
+
OPCODE(30, OP_NEG_II, "neg_ii", Ti, Ti, T0, T0)
|
|
59
|
+
OPCODE(31, OP_ADD_III, "add_iii", Ti, Ti, Ti, T0)
|
|
60
|
+
OPCODE(32, OP_SUB_III, "sub_iii", Ti, Ti, Ti, T0)
|
|
61
|
+
OPCODE(33, OP_MUL_III, "mul_iii", Ti, Ti, Ti, T0)
|
|
62
|
+
OPCODE(34, OP_DIV_III, "div_iii", Ti, Ti, Ti, T0)
|
|
63
|
+
OPCODE(35, OP_POW_III, "pow_iii", Ti, Ti, Ti, T0)
|
|
64
|
+
OPCODE(36, OP_MOD_III, "mod_iii", Ti, Ti, Ti, T0)
|
|
65
|
+
|
|
66
|
+
OPCODE(37, OP_LSHIFT_III, "lshift_iii", Ti, Ti, Ti, T0)
|
|
67
|
+
OPCODE(38, OP_RSHIFT_III, "rshift_iii", Ti, Ti, Ti, T0)
|
|
68
|
+
|
|
69
|
+
OPCODE(39, OP_WHERE_IBII, "where_ibii", Ti, Tb, Ti, Ti)
|
|
70
|
+
|
|
71
|
+
OPCODE(40, OP_CAST_LI, "cast_li", Tl, Ti, T0, T0)
|
|
72
|
+
OPCODE(41, OP_COPY_LL, "copy_ll", Tl, Tl, T0, T0)
|
|
73
|
+
OPCODE(42, OP_ONES_LIKE_LL, "ones_like_ll", Tl, T0, T0, T0)
|
|
74
|
+
OPCODE(43, OP_NEG_LL, "neg_ll", Tl, Tl, T0, T0)
|
|
75
|
+
OPCODE(44, OP_ADD_LLL, "add_lll", Tl, Tl, Tl, T0)
|
|
76
|
+
OPCODE(45, OP_SUB_LLL, "sub_lll", Tl, Tl, Tl, T0)
|
|
77
|
+
OPCODE(46, OP_MUL_LLL, "mul_lll", Tl, Tl, Tl, T0)
|
|
78
|
+
OPCODE(47, OP_DIV_LLL, "div_lll", Tl, Tl, Tl, T0)
|
|
79
|
+
OPCODE(48, OP_POW_LLL, "pow_lll", Tl, Tl, Tl, T0)
|
|
80
|
+
OPCODE(49, OP_MOD_LLL, "mod_lll", Tl, Tl, Tl, T0)
|
|
81
|
+
|
|
82
|
+
OPCODE(50, OP_LSHIFT_LLL, "lshift_lll", Tl, Tl, Tl, T0)
|
|
83
|
+
OPCODE(51, OP_RSHIFT_LLL, "rshift_lll", Tl, Tl, Tl, T0)
|
|
84
|
+
|
|
85
|
+
OPCODE(52, OP_WHERE_LBLL, "where_lbll", Tl, Tb, Tl, Tl)
|
|
86
|
+
|
|
87
|
+
OPCODE(53, OP_CAST_FI, "cast_fi", Tf, Ti, T0, T0)
|
|
88
|
+
OPCODE(54, OP_CAST_FL, "cast_fl", Tf, Tl, T0, T0)
|
|
89
|
+
OPCODE(55, OP_COPY_FF, "copy_ff", Tf, Tf, T0, T0)
|
|
90
|
+
OPCODE(56, OP_ONES_LIKE_FF, "ones_like_ff", Tf, T0, T0, T0)
|
|
91
|
+
OPCODE(57, OP_NEG_FF, "neg_ff", Tf, Tf, T0, T0)
|
|
92
|
+
OPCODE(58, OP_ADD_FFF, "add_fff", Tf, Tf, Tf, T0)
|
|
93
|
+
OPCODE(59, OP_SUB_FFF, "sub_fff", Tf, Tf, Tf, T0)
|
|
94
|
+
OPCODE(60, OP_MUL_FFF, "mul_fff", Tf, Tf, Tf, T0)
|
|
95
|
+
OPCODE(61, OP_DIV_FFF, "div_fff", Tf, Tf, Tf, T0)
|
|
96
|
+
OPCODE(62, OP_POW_FFF, "pow_fff", Tf, Tf, Tf, T0)
|
|
97
|
+
OPCODE(63, OP_MOD_FFF, "mod_fff", Tf, Tf, Tf, T0)
|
|
98
|
+
OPCODE(64, OP_SQRT_FF, "sqrt_ff", Tf, Tf, T0, T0)
|
|
99
|
+
OPCODE(65, OP_WHERE_FBFF, "where_fbff", Tf, Tb, Tf, Tf)
|
|
100
|
+
OPCODE(66, OP_FUNC_FFN, "func_ffn", Tf, Tf, Tn, T0)
|
|
101
|
+
OPCODE(67, OP_FUNC_FFFN, "func_fffn", Tf, Tf, Tf, Tn)
|
|
102
|
+
|
|
103
|
+
OPCODE(68, OP_CAST_DI, "cast_di", Td, Ti, T0, T0)
|
|
104
|
+
OPCODE(69, OP_CAST_DL, "cast_dl", Td, Tl, T0, T0)
|
|
105
|
+
OPCODE(70, OP_CAST_DF, "cast_df", Td, Tf, T0, T0)
|
|
106
|
+
OPCODE(71, OP_COPY_DD, "copy_dd", Td, Td, T0, T0)
|
|
107
|
+
OPCODE(72, OP_ONES_LIKE_DD, "ones_like_dd", Td, T0, T0, T0)
|
|
108
|
+
OPCODE(73, OP_NEG_DD, "neg_dd", Td, Td, T0, T0)
|
|
109
|
+
OPCODE(74, OP_ADD_DDD, "add_ddd", Td, Td, Td, T0)
|
|
110
|
+
OPCODE(75, OP_SUB_DDD, "sub_ddd", Td, Td, Td, T0)
|
|
111
|
+
OPCODE(76, OP_MUL_DDD, "mul_ddd", Td, Td, Td, T0)
|
|
112
|
+
OPCODE(77, OP_DIV_DDD, "div_ddd", Td, Td, Td, T0)
|
|
113
|
+
OPCODE(78, OP_POW_DDD, "pow_ddd", Td, Td, Td, T0)
|
|
114
|
+
OPCODE(79, OP_MOD_DDD, "mod_ddd", Td, Td, Td, T0)
|
|
115
|
+
OPCODE(80, OP_SQRT_DD, "sqrt_dd", Td, Td, T0, T0)
|
|
116
|
+
OPCODE(81, OP_WHERE_DBDD, "where_dbdd", Td, Tb, Td, Td)
|
|
117
|
+
OPCODE(82, OP_FUNC_DDN, "func_ddn", Td, Td, Tn, T0)
|
|
118
|
+
OPCODE(83, OP_FUNC_DDDN, "func_dddn", Td, Td, Td, Tn)
|
|
119
|
+
|
|
120
|
+
OPCODE(84, OP_EQ_BCC, "eq_bcc", Tb, Tc, Tc, T0)
|
|
121
|
+
OPCODE(85, OP_NE_BCC, "ne_bcc", Tb, Tc, Tc, T0)
|
|
122
|
+
|
|
123
|
+
OPCODE(86, OP_CAST_CI, "cast_ci", Tc, Ti, T0, T0)
|
|
124
|
+
OPCODE(87, OP_CAST_CL, "cast_cl", Tc, Tl, T0, T0)
|
|
125
|
+
OPCODE(88, OP_CAST_CF, "cast_cf", Tc, Tf, T0, T0)
|
|
126
|
+
OPCODE(89, OP_CAST_CD, "cast_cd", Tc, Td, T0, T0)
|
|
127
|
+
OPCODE(90, OP_ONES_LIKE_CC, "ones_like_cc", Tc, T0, T0, T0)
|
|
128
|
+
OPCODE(91, OP_COPY_CC, "copy_cc", Tc, Tc, T0, T0)
|
|
129
|
+
OPCODE(92, OP_NEG_CC, "neg_cc", Tc, Tc, T0, T0)
|
|
130
|
+
OPCODE(93, OP_ADD_CCC, "add_ccc", Tc, Tc, Tc, T0)
|
|
131
|
+
OPCODE(94, OP_SUB_CCC, "sub_ccc", Tc, Tc, Tc, T0)
|
|
132
|
+
OPCODE(95, OP_MUL_CCC, "mul_ccc", Tc, Tc, Tc, T0)
|
|
133
|
+
OPCODE(96, OP_DIV_CCC, "div_ccc", Tc, Tc, Tc, T0)
|
|
134
|
+
OPCODE(97, OP_WHERE_CBCC, "where_cbcc", Tc, Tb, Tc, Tc)
|
|
135
|
+
OPCODE(98, OP_FUNC_CCN, "func_ccn", Tc, Tc, Tn, T0)
|
|
136
|
+
OPCODE(99, OP_FUNC_CCCN, "func_cccn", Tc, Tc, Tc, Tn)
|
|
137
|
+
|
|
138
|
+
OPCODE(100, OP_REAL_DC, "real_dc", Td, Tc, T0, T0)
|
|
139
|
+
OPCODE(101, OP_IMAG_DC, "imag_dc", Td, Tc, T0, T0)
|
|
140
|
+
OPCODE(102, OP_COMPLEX_CDD, "complex_cdd", Tc, Td, Td, T0)
|
|
141
|
+
|
|
142
|
+
OPCODE(103, OP_COPY_SS, "copy_ss", Ts, Ts, T0, T0)
|
|
143
|
+
|
|
144
|
+
OPCODE(104, OP_WHERE_BBBB, "where_bbbb", Tb, Tb, Tb, Tb)
|
|
145
|
+
|
|
146
|
+
OPCODE(105, OP_CONTAINS_BSS, "contains_bss", Tb, Ts, Ts, T0)
|
|
147
|
+
|
|
148
|
+
OPCODE(106, OP_REDUCTION, NULL, T0, T0, T0, T0)
|
|
149
|
+
|
|
150
|
+
/* Last argument in a reduction is the axis of the array the
|
|
151
|
+
reduction should be applied along. */
|
|
152
|
+
|
|
153
|
+
OPCODE(107, OP_SUM_IIN, "sum_iin", Ti, Ti, Tn, T0)
|
|
154
|
+
OPCODE(108, OP_SUM_LLN, "sum_lln", Tl, Tl, Tn, T0)
|
|
155
|
+
OPCODE(109, OP_SUM_FFN, "sum_ffn", Tf, Tf, Tn, T0)
|
|
156
|
+
OPCODE(110, OP_SUM_DDN, "sum_ddn", Td, Td, Tn, T0)
|
|
157
|
+
OPCODE(111, OP_SUM_CCN, "sum_ccn", Tc, Tc, Tn, T0)
|
|
158
|
+
|
|
159
|
+
OPCODE(112, OP_PROD, NULL, T0, T0, T0, T0)
|
|
160
|
+
OPCODE(113, OP_PROD_IIN, "prod_iin", Ti, Ti, Tn, T0)
|
|
161
|
+
OPCODE(114, OP_PROD_LLN, "prod_lln", Tl, Tl, Tn, T0)
|
|
162
|
+
OPCODE(115, OP_PROD_FFN, "prod_ffn", Tf, Tf, Tn, T0)
|
|
163
|
+
OPCODE(116, OP_PROD_DDN, "prod_ddn", Td, Td, Tn, T0)
|
|
164
|
+
OPCODE(117, OP_PROD_CCN, "prod_ccn", Tc, Tc, Tn, T0)
|
|
165
|
+
|
|
166
|
+
OPCODE(118, OP_MIN, NULL, T0, T0, T0, T0)
|
|
167
|
+
OPCODE(119, OP_MIN_IIN, "min_iin", Ti, Ti, Tn, T0)
|
|
168
|
+
OPCODE(120, OP_MIN_LLN, "min_lln", Tl, Tl, Tn, T0)
|
|
169
|
+
OPCODE(121, OP_MIN_FFN, "min_ffn", Tf, Tf, Tn, T0)
|
|
170
|
+
OPCODE(122, OP_MIN_DDN, "min_ddn", Td, Td, Tn, T0)
|
|
171
|
+
|
|
172
|
+
OPCODE(123, OP_MAX, NULL, T0, T0, T0, T0)
|
|
173
|
+
OPCODE(124, OP_MAX_IIN, "max_iin", Ti, Ti, Tn, T0)
|
|
174
|
+
OPCODE(125, OP_MAX_LLN, "max_lln", Tl, Tl, Tn, T0)
|
|
175
|
+
OPCODE(126, OP_MAX_FFN, "max_ffn", Tf, Tf, Tn, T0)
|
|
176
|
+
OPCODE(127, OP_MAX_DDN, "max_ddn", Td, Td, Tn, T0)
|
|
177
|
+
|
|
178
|
+
/* Should be the last opcode */
|
|
179
|
+
OPCODE(128, OP_END, NULL, T0, T0, T0, T0)
|