numexpr 2.11.0__tar.gz → 2.12.1__tar.gz
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-2.12.1/ADDFUNCS.rst +241 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/ANNOUNCE.rst +10 -16
- numexpr-2.12.1/LICENSES/cpuinfo.txt +31 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/PKG-INFO +4 -3
- {numexpr-2.11.0 → numexpr-2.12.1}/README.rst +1 -1
- {numexpr-2.11.0 → numexpr-2.12.1}/RELEASE_NOTES.rst +28 -1
- numexpr-2.12.1/VERSION +1 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/complex_functions.hpp +29 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/expressions.py +6 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/functions.hpp +42 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/interp_body.cpp +29 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/interpreter.cpp +155 -4
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/interpreter.hpp +18 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/module.cpp +6 -1
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/msvc_function_stubs.hpp +27 -3
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/necompiler.py +6 -3
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/numexpr_config.hpp +11 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/opcodes.hpp +40 -26
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/tests/conftest.py +1 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/tests/test_numexpr.py +22 -2
- numexpr-2.12.1/numexpr/version.py +5 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr.egg-info/PKG-INFO +4 -3
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr.egg-info/SOURCES.txt +2 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/pyproject.toml +17 -3
- {numexpr-2.11.0 → numexpr-2.12.1}/site.cfg.example +5 -3
- numexpr-2.11.0/VERSION +0 -1
- numexpr-2.11.0/numexpr/version.py +0 -5
- {numexpr-2.11.0 → numexpr-2.12.1}/AUTHORS.txt +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/LICENSE.txt +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/MANIFEST.in +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/boolean_timing.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/free_threading.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/issue-36.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/issue-47.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/large_array_vs_numpy.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/multidim.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/poly.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/timing.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/unaligned-simple.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/varying-expr.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/vml_timing.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/vml_timing2.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/bench/vml_timing3.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/__init__.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/cpuinfo.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/missing_posix_functions.hpp +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/module.hpp +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/numexpr_object.cpp +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/numexpr_object.hpp +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/str-two-way.hpp +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/tests/__init__.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/utils.py +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/win32/pthread.c +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/win32/pthread.h +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/win32/stdint.h +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr.egg-info/dependency_links.txt +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr.egg-info/requires.txt +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/numexpr.egg-info/top_level.txt +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/requirements.txt +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/setup.cfg +0 -0
- {numexpr-2.11.0 → numexpr-2.12.1}/setup.py +0 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
Functions and Function signatures
|
|
2
|
+
=================================
|
|
3
|
+
|
|
4
|
+
Adding functions
|
|
5
|
+
----------------
|
|
6
|
+
|
|
7
|
+
In order to add new functions to ``numexpr``, currently it is necessary to edit several files. Consider adding a function
|
|
8
|
+
``out_type myfunc(arg_type)``.
|
|
9
|
+
|
|
10
|
+
* ``numexpr/expressions.py``
|
|
11
|
+
Add ``'myfunc': func(numpy.myfunc, out_dtype),`` to the dict of functions, ``functions = {...``. If the return type of the function is ``bool``, add
|
|
12
|
+
the function to the list ``if opcode in ("isnan", "isfinite"):`` in the ``__init__`` function of the ``FuncNode`` class.
|
|
13
|
+
In the future it might be nice to refactor this function since it sets the output type based on the type of the inputs in general.
|
|
14
|
+
|
|
15
|
+
* ``numexpr/necompiler.py``
|
|
16
|
+
Add ``"myfunc"`` to the list of functions:
|
|
17
|
+
|
|
18
|
+
.. code-block:: python3
|
|
19
|
+
|
|
20
|
+
"floor",
|
|
21
|
+
"isnan",
|
|
22
|
+
"isfinite",
|
|
23
|
+
"myfunc"
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
* ``numexpr/functions.hpp``
|
|
27
|
+
Find the correct function signature ``FUNC_OA`` where ``O`` is the return type, and ``A`` the argument type(s). For example, if the function
|
|
28
|
+
is ``double myfunc(double)``, one should edit within the ``FUNC_DD`` clause. If you cannot find your function signature you will have to add it,
|
|
29
|
+
following the template of the other functions.
|
|
30
|
+
Most likely, you will want to add support for several function signatures (e.g. double -> bool and float -> bool) and so you will have to add the
|
|
31
|
+
function in two clauses. If your function has a float input, you will see that there are 5 arguments in the
|
|
32
|
+
``FUNC_OA`` macro, and you will have to add ``myfunc2`` here is order to compile on MSVC machines (i.e. Windows, see following).
|
|
33
|
+
Example:
|
|
34
|
+
|
|
35
|
+
.. code-block:: cpp
|
|
36
|
+
:emphasize-lines: 6, 20
|
|
37
|
+
|
|
38
|
+
#ifndef FUNC_DD
|
|
39
|
+
#define ELIDE_FUNC_DD
|
|
40
|
+
#define FUNC_DD(...)
|
|
41
|
+
#endif
|
|
42
|
+
...
|
|
43
|
+
FUNC_DD(FUNC_MYFUNC_DD, "myfunc_dd", myfunc, vdMyfunc)
|
|
44
|
+
FUNC_DD(FUNC_DD_LAST, NULL, NULL, NULL)
|
|
45
|
+
#ifdef ELIDE_FUNC_DD
|
|
46
|
+
#undef ELIDE_FUNC_DD
|
|
47
|
+
#undef FUNC_DD
|
|
48
|
+
#endif
|
|
49
|
+
|
|
50
|
+
...
|
|
51
|
+
|
|
52
|
+
#ifndef FUNC_FF
|
|
53
|
+
#define ELIDE_FUNC_FF
|
|
54
|
+
#define FUNC_FF(...)
|
|
55
|
+
#endif
|
|
56
|
+
...
|
|
57
|
+
FUNC_FF(FUNC_MYFUNC_FF, "myfunc_ff", myfuncf, myfuncf2, vfMyfunc)
|
|
58
|
+
FUNC_FF(FUNC_FF_LAST, NULL, NULL, NULL, NULL)
|
|
59
|
+
#ifdef ELIDE_FUNC_FF
|
|
60
|
+
#undef ELIDE_FUNC_FF
|
|
61
|
+
#undef FUNC_FF
|
|
62
|
+
#endif
|
|
63
|
+
|
|
64
|
+
* ``numexpr/msvc_function_stubs.hpp``
|
|
65
|
+
In order to support float arguments, due to oddities of MSVC, you have to provide explicit support for your function in this file.
|
|
66
|
+
Add ``#define myfuncf(x) ((float)floor((double)(x)))`` (if your function is float -> float) to the ``#if`` clause at the top of the file
|
|
67
|
+
which is for old versions of MSVC which did not have support for single precision fucntions. Then in the body, add an inline function
|
|
68
|
+
|
|
69
|
+
.. code-block:: cpp
|
|
70
|
+
|
|
71
|
+
inline float myfuncf2(float x) {
|
|
72
|
+
return myfuncf(x);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
This is the function that appears as the ``f_win32`` parameter in ``functions.hpp``.
|
|
76
|
+
|
|
77
|
+
* ``numexpr/tests/test_numexpr.py``
|
|
78
|
+
Don't forget to add a test for your function!
|
|
79
|
+
|
|
80
|
+
Adding function signatures
|
|
81
|
+
--------------------------
|
|
82
|
+
It may so happen that you cannot find your desired function signature in ``functions.hpp``. This means you will have to add it yourself!
|
|
83
|
+
This involves editing a few more files. In addition, there may be certain bespoke changes, specific to the function signature
|
|
84
|
+
that you may have to make (see Notes, below)
|
|
85
|
+
|
|
86
|
+
* ``numexpr/functions.hpp``
|
|
87
|
+
Firstly, add clause(s) for your function signature. For example, if the function signature is ``bool(double)`` and ``bool(float)``, add
|
|
88
|
+
``FUNC_BD`` and ``FUNC_BF`` clauses (in the latter case you will need the macro to take 5 arguments for MSVC-compatibility.)
|
|
89
|
+
|
|
90
|
+
.. code-block:: cpp
|
|
91
|
+
|
|
92
|
+
#ifndef FUNC_BD
|
|
93
|
+
#define ELIDE_FUNC_BD
|
|
94
|
+
#define FUNC_BD(...)
|
|
95
|
+
#endif
|
|
96
|
+
...
|
|
97
|
+
FUNC_BD(FUNC_BD_LAST, NULL, NULL, NULL)
|
|
98
|
+
#ifdef ELIDE_FUNC_BD
|
|
99
|
+
#undef ELIDE_FUNC_BD
|
|
100
|
+
#undef FUNC_BD
|
|
101
|
+
#endif
|
|
102
|
+
|
|
103
|
+
#ifndef FUNC_BF
|
|
104
|
+
#define ELIDE_FUNC_BF
|
|
105
|
+
#define FUNC_BF(...)
|
|
106
|
+
#endif
|
|
107
|
+
...
|
|
108
|
+
FUNC_BF(FUNC_BF_LAST, NULL, NULL, NULL, NULL)
|
|
109
|
+
#ifdef ELIDE_FUNC_BF
|
|
110
|
+
#undef ELIDE_FUNC_BF
|
|
111
|
+
#undef FUNC_BF
|
|
112
|
+
#endif
|
|
113
|
+
|
|
114
|
+
The ultimate source of the functions in the macro ``FUNC_BF(...)`` are the headers included in ``numexpr/interpreter.cpp`` (in particular
|
|
115
|
+
``numexpr/numexpr_config.hpp``, which can be used to overwrite ``<math.h>`` functions), so the functions should be available from there.
|
|
116
|
+
|
|
117
|
+
* ``numexpr/interp_body.cpp``
|
|
118
|
+
Add case support for OPCODES associated to your new function signatures via e.g. ``case OP_FUNC_BFN`` and ``case OP_FUNC_BDN``, following
|
|
119
|
+
the framework suggested by the other functions:
|
|
120
|
+
|
|
121
|
+
.. code-block:: cpp
|
|
122
|
+
|
|
123
|
+
case OP_FUNC_BFN:
|
|
124
|
+
#ifdef USE_VML
|
|
125
|
+
VEC_ARG1_VML(functions_bf_vml[arg2](BLOCK_SIZE,
|
|
126
|
+
(float*)x1, (bool*)dest));
|
|
127
|
+
#else
|
|
128
|
+
VEC_ARG1(b_dest = functions_bf[arg2](f1));
|
|
129
|
+
#endif
|
|
130
|
+
|
|
131
|
+
Note that it is important that the out variable matches the output type of the function (i.e. ``b_dest`` for bool, ``f_dest`` for float etc.)
|
|
132
|
+
|
|
133
|
+
* ``numexpr/interpreter.hpp``
|
|
134
|
+
Add clauses to read the ``functions.hpp`` macros correctly
|
|
135
|
+
|
|
136
|
+
.. code-block:: cpp
|
|
137
|
+
|
|
138
|
+
enum FuncBFCodes {
|
|
139
|
+
#define FUNC_BF(fop, ...) fop,
|
|
140
|
+
#include "functions.hpp"
|
|
141
|
+
#undef FUNC_BF
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
* ``numexpr/interpreter.cpp``
|
|
145
|
+
Add clauses to generate the FUNC_CODES from the ``functions.hpp`` header, making sure to include clauses for ``_WIN32`` and
|
|
146
|
+
``VML`` as necessary accoridng to the framework suggested by the other functions.
|
|
147
|
+
|
|
148
|
+
.. code-block:: cpp
|
|
149
|
+
|
|
150
|
+
typedef bool (*FuncBFPtr)(float);
|
|
151
|
+
#ifdef _WIN32
|
|
152
|
+
FuncBFPtr functions_bf[] = {
|
|
153
|
+
#define FUNC_BF(fop, s, f, f_win32, ...) f_win32,
|
|
154
|
+
#include "functions.hpp"
|
|
155
|
+
#undef FUNC_BF
|
|
156
|
+
};
|
|
157
|
+
#else
|
|
158
|
+
FuncBFPtr functions_bf[] = {
|
|
159
|
+
#define FUNC_BF(fop, s, f, ...) f,
|
|
160
|
+
#include "functions.hpp"
|
|
161
|
+
#undef FUNC_BF
|
|
162
|
+
};
|
|
163
|
+
#endif
|
|
164
|
+
|
|
165
|
+
#ifdef USE_VML
|
|
166
|
+
typedef void (*FuncBFPtr_vml)(MKL_INT, const float*, bool*);
|
|
167
|
+
FuncBFPtr_vml functions_bf_vml[] = {
|
|
168
|
+
#define FUNC_BF(fop, s, f, f_win32, f_vml) f_vml,
|
|
169
|
+
#include "functions.hpp"
|
|
170
|
+
#undef FUNC_BF
|
|
171
|
+
};
|
|
172
|
+
#endif
|
|
173
|
+
|
|
174
|
+
Some functions (e.g. ``fmod``, ``isnan``) are not available in MKL, and so must be hard-coded here as well:
|
|
175
|
+
|
|
176
|
+
.. code-block:: cpp
|
|
177
|
+
|
|
178
|
+
#ifdef USE_VML
|
|
179
|
+
/* no isnan, isfinite or isinf in VML */
|
|
180
|
+
static void vdIsfinite(MKL_INT n, const double* x1, bool* dest)
|
|
181
|
+
{
|
|
182
|
+
MKL_INT j;
|
|
183
|
+
for (j=0; j<n; j++) {
|
|
184
|
+
dest[j] = isfinited(x1[j]);
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
#endif
|
|
188
|
+
|
|
189
|
+
The complex case is slightlñy different (see other examples in the same file).
|
|
190
|
+
|
|
191
|
+
Add case handling to the ``check_program`` function
|
|
192
|
+
|
|
193
|
+
.. code-block:: cpp
|
|
194
|
+
|
|
195
|
+
else if (op == OP_FUNC_BDN) {
|
|
196
|
+
if (arg < 0 || arg >= FUNC_BD_LAST) {
|
|
197
|
+
PyErr_Format(PyExc_RuntimeError, "invalid program: funccode out of range (%i) at %i", arg, argloc);
|
|
198
|
+
return -1;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else if (op == OP_FUNC_BFN) {
|
|
202
|
+
if (arg < 0 || arg >= FUNC_BF_LAST) {
|
|
203
|
+
PyErr_Format(PyExc_RuntimeError, "invalid program: funccode out of range (%i) at %i", arg, argloc);
|
|
204
|
+
return -1;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
* ``numexpr/module.cpp``
|
|
209
|
+
Add code here to define the ``FUNC_OA`` macros you require
|
|
210
|
+
|
|
211
|
+
.. code-block:: cpp
|
|
212
|
+
|
|
213
|
+
#define FUNC_BF(name, sname, ...) add_func(name, sname);
|
|
214
|
+
#define FUNC_BD(name, sname, ...) add_func(name, sname);
|
|
215
|
+
...
|
|
216
|
+
#include "functions.hpp"
|
|
217
|
+
...
|
|
218
|
+
#undef FUNC_BD
|
|
219
|
+
#undef FUNC_BF
|
|
220
|
+
|
|
221
|
+
* ``numexpr/opcodes.hpp``
|
|
222
|
+
Finally, add the ``OP_FUNC_BDN`` etc. codes here. It is necessary for the OPCODES in the file to be in (ascending order) with
|
|
223
|
+
``NOOP`` as 0 and ``OP_LAST`` as the largest number. Secondly, all reduction OPCODES must appear last. Hence, after adding your
|
|
224
|
+
function signatures (just before the reduction OPCODES) it is necessary to increment all succeeding OPCODES.
|
|
225
|
+
|
|
226
|
+
.. code-block:: cpp
|
|
227
|
+
|
|
228
|
+
OPCODE(106, OP_FUNC_BDN, "func_bdn", Tb, Td, Tn, T0)
|
|
229
|
+
OPCODE(107, OP_FUNC_BFN, "func_bfn", Tb, Tf, Tn, T0)
|
|
230
|
+
|
|
231
|
+
Notes
|
|
232
|
+
-----
|
|
233
|
+
In many cases this process will not be very smooth since one relies on the internal C/C++ standard functions (which can be fussy, to varying degrees on different platforms). Some common gotchas are then:
|
|
234
|
+
|
|
235
|
+
* OPCODES are currently only supported up to 255 - if it becomes necessary to increment further, one will have to change the ``latin_1`` encoding used in ``quadrupleToString`` in ``necompiler.py``. In addition, since the OPCDE table is assumed to be of type ``unsigned char`` the ``get_return_sig`` function in ``numexpr/interpreter.cpp`` may have to be changed (possibly other changes too).
|
|
236
|
+
|
|
237
|
+
* Depending on the new function signature (above all if the out type is different to the input types), one may have to edit the ``__init__`` function in the ``FuncNode`` class in ``expressions.py``.
|
|
238
|
+
|
|
239
|
+
* Functions which accept and/or return complex arguments must be added to the ``complex_functions.hpp`` file (take care when adding them in ``interpreter.cpp`` and ``interp_body.cpp``, since their signatures are usually a bit different).
|
|
240
|
+
|
|
241
|
+
* Depending on MSVC support, namespace clashes, casting problems, it may be necessary to make various changes to ``numexpr/numexpr_config.hpp`` and ``numexpr/msvc_function_stubs.hpp``. For example, in PR #523, non-clashing wrappers were introduced for ``isnan`` and ``isfinite`` since the float versions ``isnanf, isfinitef`` were inconsistently defined (and output ints) - depending on how strict the platform interpreter is, the implicit cast from int to bool was acceptable or not for example. In addition, the base functions were in different namespaces or had different names across platforms.
|
|
@@ -1,33 +1,27 @@
|
|
|
1
1
|
=========================
|
|
2
|
-
Announcing NumExpr 2.
|
|
2
|
+
Announcing NumExpr 2.12.1
|
|
3
3
|
=========================
|
|
4
4
|
|
|
5
5
|
Hi everyone,
|
|
6
6
|
|
|
7
|
-
NumExpr 2.
|
|
8
|
-
|
|
9
|
-
Finally, Python 3.10 is now the minimum supported version.
|
|
7
|
+
NumExpr 2.12.1 allows isnan/isfinite/isinf functions to be used with complex.
|
|
8
|
+
Also, OneAPI MKL has been fixed. Thanks to Luke Shaw for these contributions.
|
|
10
9
|
|
|
11
10
|
Project documentation is available at:
|
|
12
11
|
|
|
13
12
|
http://numexpr.readthedocs.io/
|
|
14
13
|
|
|
15
|
-
Changes from 2.
|
|
14
|
+
Changes from 2.12.0 to 2.12.1
|
|
16
15
|
-----------------------------
|
|
17
16
|
|
|
18
|
-
*
|
|
19
|
-
|
|
20
|
-
For more info, see discussions PRs #504, #505 and #508.
|
|
21
|
-
Thanks to @andfoy, @rgommers and @FrancescAlted for the work.
|
|
17
|
+
* Added complex counterparts for isnan/isfinite/isinf functions.
|
|
18
|
+
Thanks to Luke Shaw.
|
|
22
19
|
|
|
23
|
-
*
|
|
24
|
-
|
|
25
|
-
for the fix.
|
|
20
|
+
* Updated documentation for the new functions and instructions
|
|
21
|
+
for adding new functions to the virtual machine. Thanks to Luke Shaw.
|
|
26
22
|
|
|
27
|
-
*
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
* Python 3.10 is now the minimum supported version.
|
|
23
|
+
* Fixed MKL support; it was broken in 2.12.0. Thanks to
|
|
24
|
+
Christoph Gohlke for reporting the issue.
|
|
31
25
|
|
|
32
26
|
What's Numexpr?
|
|
33
27
|
---------------
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Copyright statement for `cpuinfo` module.
|
|
2
|
+
|
|
3
|
+
Copyright 2002 Pearu Peterson all rights reserved,
|
|
4
|
+
Pearu Peterson <pearu@cens.ioc.ee>
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
* Redistributions of source code must retain the above copyright
|
|
10
|
+
notice, this list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
* Redistributions in binary form must reproduce the above
|
|
13
|
+
copyright notice, this list of conditions and the following
|
|
14
|
+
disclaimer in the documentation and/or other materials provided
|
|
15
|
+
with the distribution.
|
|
16
|
+
|
|
17
|
+
* Neither the name of Pearu Peterson nor the names of its
|
|
18
|
+
contributors may be used to endorse or promote products derived
|
|
19
|
+
from this software without specific prior written permission.
|
|
20
|
+
|
|
21
|
+
HIS SOFTWARE IS PROVIDED BY PEARU PETERSON ''AS IS'' AND ANY EXPRESS
|
|
22
|
+
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
23
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
24
|
+
DISCLAIMED. IN NO EVENT SHALL PEARU PETERSON BE LIABLE FOR ANY DIRECT,
|
|
25
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
26
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
27
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
28
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
29
|
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
30
|
+
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
31
|
+
POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: numexpr
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.12.1
|
|
4
4
|
Summary: Fast numerical expression evaluator for NumPy
|
|
5
5
|
Author-email: "David M. Cooke, Francesc Alted, and others" <blosc@blosc.org>
|
|
6
6
|
Maintainer-email: Blosc Development Team <blosc@blosc.org>
|
|
@@ -21,10 +21,11 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
25
|
Requires-Python: >=3.10
|
|
25
26
|
Description-Content-Type: text/x-rst
|
|
26
27
|
License-File: LICENSE.txt
|
|
27
|
-
License-File:
|
|
28
|
+
License-File: LICENSES/cpuinfo.txt
|
|
28
29
|
Requires-Dist: numpy>=1.23.0
|
|
29
30
|
Dynamic: license-file
|
|
30
31
|
|
|
@@ -136,7 +137,7 @@ See `requirements.txt` for the required version of NumPy.
|
|
|
136
137
|
|
|
137
138
|
NumExpr is built in the standard Python way::
|
|
138
139
|
|
|
139
|
-
|
|
140
|
+
pip install [-e] .
|
|
140
141
|
|
|
141
142
|
You can test `numexpr` with::
|
|
142
143
|
|
|
@@ -1,7 +1,33 @@
|
|
|
1
1
|
=====================================
|
|
2
|
-
Release notes for NumExpr 2.
|
|
2
|
+
Release notes for NumExpr 2.12 series
|
|
3
3
|
=====================================
|
|
4
4
|
|
|
5
|
+
Changes from 2.12.0 to 2.12.1
|
|
6
|
+
-----------------------------
|
|
7
|
+
|
|
8
|
+
* Added complex counterparts for isnan/isfinite/isinf functions.
|
|
9
|
+
Thanks to Luke Shaw.
|
|
10
|
+
|
|
11
|
+
* Updated documentation for the new functions and instructions
|
|
12
|
+
for adding new functions to the virtual machine. Thanks to Luke Shaw.
|
|
13
|
+
|
|
14
|
+
* Fixed MKL support; it was broken in 2.12.0. Thanks to
|
|
15
|
+
Christoph Gohlke for reporting the issue.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Changes from 2.11.0 to 2.12.0
|
|
19
|
+
-----------------------------
|
|
20
|
+
|
|
21
|
+
* Added isnan/isfinite/isinf functions. Thanks to Luke Shaw.
|
|
22
|
+
|
|
23
|
+
* New instructions for adding new functions to the virtual machine.
|
|
24
|
+
They are available at ADDFUNCS.rst. Thanks to Luke Shaw.
|
|
25
|
+
|
|
26
|
+
* We are distributing binary wheels for Python 3.14 and 3.14t now.
|
|
27
|
+
|
|
28
|
+
* We are distributing musllinux wheels too! Thanks to Clément Robert.
|
|
29
|
+
|
|
30
|
+
|
|
5
31
|
Changes from 2.10.2 to 2.11.0
|
|
6
32
|
-----------------------------
|
|
7
33
|
|
|
@@ -19,6 +45,7 @@ Changes from 2.10.2 to 2.11.0
|
|
|
19
45
|
|
|
20
46
|
* Python 3.10 is now the minimum supported version.
|
|
21
47
|
|
|
48
|
+
|
|
22
49
|
Changes from 2.10.1 to 2.10.2
|
|
23
50
|
-----------------------------
|
|
24
51
|
|
numexpr-2.12.1/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.12.1
|
|
@@ -424,4 +424,33 @@ nc_abs(std::complex<double> *x, std::complex<double> *r)
|
|
|
424
424
|
r->imag(0);
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
+
static bool
|
|
428
|
+
nc_isinf(std::complex<double> *x)
|
|
429
|
+
{
|
|
430
|
+
double xr=x->real(), xi=x->imag();
|
|
431
|
+
bool bi,br;
|
|
432
|
+
bi = isinfd(xi);
|
|
433
|
+
br = isinfd(xr);
|
|
434
|
+
return bi || br;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
static bool
|
|
438
|
+
nc_isnan(std::complex<double> *x)
|
|
439
|
+
{
|
|
440
|
+
double xr=x->real(), xi=x->imag();
|
|
441
|
+
bool bi,br;
|
|
442
|
+
bi = isnand(xi);
|
|
443
|
+
br = isnand(xr);
|
|
444
|
+
return bi || br;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
static bool
|
|
448
|
+
nc_isfinite(std::complex<double> *x)
|
|
449
|
+
{
|
|
450
|
+
double xr=x->real(), xi=x->imag();
|
|
451
|
+
bool bi,br;
|
|
452
|
+
bi = isfinited(xi);
|
|
453
|
+
br = isfinited(xr);
|
|
454
|
+
return bi && br;
|
|
455
|
+
}
|
|
427
456
|
#endif // NUMEXPR_COMPLEX_FUNCTIONS_HPP
|
|
@@ -366,6 +366,10 @@ functions = {
|
|
|
366
366
|
'complex': func(complex, 'complex'),
|
|
367
367
|
'conj': func(numpy.conj, 'complex'),
|
|
368
368
|
|
|
369
|
+
'isnan': func(numpy.isnan, 'bool'),
|
|
370
|
+
'isfinite': func(numpy.isfinite, 'bool'),
|
|
371
|
+
'isinf': func(numpy.isinf, 'bool'),
|
|
372
|
+
|
|
369
373
|
'sum': gen_reduce_axis_func('sum'),
|
|
370
374
|
'prod': gen_reduce_axis_func('prod'),
|
|
371
375
|
'min': gen_reduce_axis_func('min'),
|
|
@@ -521,4 +525,6 @@ class FuncNode(OpNode):
|
|
|
521
525
|
def __init__(self, opcode=None, args=None, kind=None):
|
|
522
526
|
if (kind is None) and (args is not None):
|
|
523
527
|
kind = commonKind(args)
|
|
528
|
+
if opcode in ("isnan", "isfinite", "isinf"): # bodge for boolean return functions
|
|
529
|
+
kind = 'bool'
|
|
524
530
|
OpNode.__init__(self, opcode, args, kind)
|
|
@@ -86,6 +86,34 @@ FUNC_DD(FUNC_DD_LAST, NULL, NULL, NULL)
|
|
|
86
86
|
#undef FUNC_DD
|
|
87
87
|
#endif
|
|
88
88
|
|
|
89
|
+
// double -> boolean functions
|
|
90
|
+
#ifndef FUNC_BD
|
|
91
|
+
#define ELIDE_FUNC_BD
|
|
92
|
+
#define FUNC_BD(...)
|
|
93
|
+
#endif
|
|
94
|
+
FUNC_BD(FUNC_ISNAN_BD, "isnan_bd", isnand, vdIsnan)
|
|
95
|
+
FUNC_BD(FUNC_ISFINITE_BD, "isfinite_bd", isfinited, vdIsfinite)
|
|
96
|
+
FUNC_BD(FUNC_ISINF_BD, "isinf_bd", isinfd, vdIsinf)
|
|
97
|
+
FUNC_BD(FUNC_BD_LAST, NULL, NULL, NULL)
|
|
98
|
+
#ifdef ELIDE_FUNC_BD
|
|
99
|
+
#undef ELIDE_FUNC_BD
|
|
100
|
+
#undef FUNC_BD
|
|
101
|
+
#endif
|
|
102
|
+
|
|
103
|
+
// float -> boolean functions (C99 defines the same function for all types)
|
|
104
|
+
#ifndef FUNC_BF
|
|
105
|
+
#define ELIDE_FUNC_BF
|
|
106
|
+
#define FUNC_BF(...)
|
|
107
|
+
#endif // use wrappers as there is name collision with isnanf in std
|
|
108
|
+
FUNC_BF(FUNC_ISNAN_BF, "isnan_bf", isnanf_, isnanf2, vfIsnan)
|
|
109
|
+
FUNC_BF(FUNC_ISFINITE_BF, "isfinite_bf", isfinitef_, isfinitef2, vfIsfinite)
|
|
110
|
+
FUNC_BF(FUNC_ISINF_BF, "isinf_bf", isinff_, isinff2, vfIsinf)
|
|
111
|
+
FUNC_BF(FUNC_BF_LAST, NULL, NULL, NULL, NULL)
|
|
112
|
+
#ifdef ELIDE_FUNC_BF
|
|
113
|
+
#undef ELIDE_FUNC_BF
|
|
114
|
+
#undef FUNC_BF
|
|
115
|
+
#endif
|
|
116
|
+
|
|
89
117
|
#ifndef FUNC_DDD
|
|
90
118
|
#define ELIDE_FUNC_DDD
|
|
91
119
|
#define FUNC_DDD(...)
|
|
@@ -138,3 +166,17 @@ FUNC_CCC(FUNC_CCC_LAST, NULL, NULL)
|
|
|
138
166
|
#undef ELIDE_FUNC_CCC
|
|
139
167
|
#undef FUNC_CCC
|
|
140
168
|
#endif
|
|
169
|
+
|
|
170
|
+
// complex -> boolean functions
|
|
171
|
+
#ifndef FUNC_BC
|
|
172
|
+
#define ELIDE_FUNC_BC
|
|
173
|
+
#define FUNC_BC(...)
|
|
174
|
+
#endif // use wrappers as there is name collision with isnanf in std
|
|
175
|
+
FUNC_BC(FUNC_ISNAN_BC, "isnan_bc", nc_isnan, vzIsnan)
|
|
176
|
+
FUNC_BC(FUNC_ISFINITE_BC, "isfinite_bc", nc_isfinite, vzIsfinite)
|
|
177
|
+
FUNC_BC(FUNC_ISINF_BC, "isinf_bc", nc_isinf, vzIsinf)
|
|
178
|
+
FUNC_BC(FUNC_BC_LAST, NULL, NULL, NULL)
|
|
179
|
+
#ifdef ELIDE_FUNC_BC
|
|
180
|
+
#undef ELIDE_FUNC_BC
|
|
181
|
+
#undef FUNC_BC
|
|
182
|
+
#endif
|
|
@@ -451,6 +451,35 @@
|
|
|
451
451
|
case OP_COMPLEX_CDD: VEC_ARG2(cr_dest = d1;
|
|
452
452
|
ci_dest = d2);
|
|
453
453
|
|
|
454
|
+
// Boolean return types
|
|
455
|
+
case OP_FUNC_BFN:
|
|
456
|
+
#ifdef USE_VML
|
|
457
|
+
VEC_ARG1_VML(functions_bf_vml[arg2](BLOCK_SIZE,
|
|
458
|
+
(float*)x1, (bool*)dest));
|
|
459
|
+
#else
|
|
460
|
+
VEC_ARG1(b_dest = functions_bf[arg2](f1));
|
|
461
|
+
#endif
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
case OP_FUNC_BDN:
|
|
465
|
+
#ifdef USE_VML
|
|
466
|
+
VEC_ARG1_VML(functions_bd_vml[arg2](BLOCK_SIZE,
|
|
467
|
+
(double*)x1, (bool*)dest));
|
|
468
|
+
#else
|
|
469
|
+
VEC_ARG1(b_dest = functions_bd[arg2](d1));
|
|
470
|
+
#endif
|
|
471
|
+
|
|
472
|
+
case OP_FUNC_BCN:
|
|
473
|
+
#ifdef USE_VML
|
|
474
|
+
VEC_ARG1_VML(functions_bc_vml[arg2](BLOCK_SIZE,
|
|
475
|
+
(const MKL_Complex16*)x1, (bool*)dest));
|
|
476
|
+
#else
|
|
477
|
+
VEC_ARG1(ca.real(c1r);
|
|
478
|
+
ca.imag(c1i);
|
|
479
|
+
b_dest = functions_bc[arg2](&ca));
|
|
480
|
+
#endif
|
|
481
|
+
|
|
482
|
+
|
|
454
483
|
/* Reductions */
|
|
455
484
|
case OP_SUM_IIN: VEC_ARG1(i_reduce += i1);
|
|
456
485
|
case OP_SUM_LLN: VEC_ARG1(l_reduce += l1);
|
|
@@ -204,6 +204,138 @@ FuncDDPtr functions_dd[] = {
|
|
|
204
204
|
#undef FUNC_DD
|
|
205
205
|
};
|
|
206
206
|
|
|
207
|
+
// Boolean output functions
|
|
208
|
+
typedef bool (*FuncBFPtr)(float);
|
|
209
|
+
#ifdef _WIN32
|
|
210
|
+
FuncBFPtr functions_bf[] = {
|
|
211
|
+
#define FUNC_BF(fop, s, f, f_win32, ...) f_win32,
|
|
212
|
+
#include "functions.hpp"
|
|
213
|
+
#undef FUNC_BF
|
|
214
|
+
};
|
|
215
|
+
#else
|
|
216
|
+
FuncBFPtr functions_bf[] = {
|
|
217
|
+
#define FUNC_BF(fop, s, f, ...) f,
|
|
218
|
+
#include "functions.hpp"
|
|
219
|
+
#undef FUNC_BF
|
|
220
|
+
};
|
|
221
|
+
#endif
|
|
222
|
+
|
|
223
|
+
#ifdef USE_VML
|
|
224
|
+
/* no isnan, isfinite or isinf in VML */
|
|
225
|
+
static void vfIsfinite(MKL_INT n, const float* x1, bool* dest)
|
|
226
|
+
{
|
|
227
|
+
MKL_INT j;
|
|
228
|
+
for (j=0; j<n; j++) {
|
|
229
|
+
dest[j] = isfinitef_(x1[j]);
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
static void vfIsinf(MKL_INT n, const float* x1, bool* dest)
|
|
233
|
+
{
|
|
234
|
+
MKL_INT j;
|
|
235
|
+
for (j=0; j<n; j++) {
|
|
236
|
+
dest[j] = isinff_(x1[j]);
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
static void vfIsnan(MKL_INT n, const float* x1, bool* dest)
|
|
240
|
+
{
|
|
241
|
+
MKL_INT j;
|
|
242
|
+
for (j=0; j<n; j++) {
|
|
243
|
+
dest[j] = isnanf_(x1[j]);
|
|
244
|
+
};
|
|
245
|
+
};
|
|
246
|
+
#endif
|
|
247
|
+
|
|
248
|
+
#ifdef USE_VML
|
|
249
|
+
typedef void (*FuncBFPtr_vml)(MKL_INT, const float*, bool*);
|
|
250
|
+
FuncBFPtr_vml functions_bf_vml[] = {
|
|
251
|
+
#define FUNC_BF(fop, s, f, f_win32, f_vml) f_vml,
|
|
252
|
+
#include "functions.hpp"
|
|
253
|
+
#undef FUNC_BF
|
|
254
|
+
};
|
|
255
|
+
#endif
|
|
256
|
+
|
|
257
|
+
typedef bool (*FuncBDPtr)(double);
|
|
258
|
+
FuncBDPtr functions_bd[] = {
|
|
259
|
+
#define FUNC_BD(fop, s, f, ...) f,
|
|
260
|
+
#include "functions.hpp"
|
|
261
|
+
#undef FUNC_BD
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
#ifdef USE_VML
|
|
265
|
+
/* no isnan, isfinite or isinf in VML */
|
|
266
|
+
static void vdIsfinite(MKL_INT n, const double* x1, bool* dest)
|
|
267
|
+
{
|
|
268
|
+
MKL_INT j;
|
|
269
|
+
for (j=0; j<n; j++) {
|
|
270
|
+
dest[j] = isfinited(x1[j]);
|
|
271
|
+
};
|
|
272
|
+
};
|
|
273
|
+
static void vdIsinf(MKL_INT n, const double* x1, bool* dest)
|
|
274
|
+
{
|
|
275
|
+
MKL_INT j;
|
|
276
|
+
for (j=0; j<n; j++) {
|
|
277
|
+
dest[j] = isinfd(x1[j]);
|
|
278
|
+
};
|
|
279
|
+
};
|
|
280
|
+
static void vdIsnan(MKL_INT n, const double* x1, bool* dest)
|
|
281
|
+
{
|
|
282
|
+
MKL_INT j;
|
|
283
|
+
for (j=0; j<n; j++) {
|
|
284
|
+
dest[j] = isnand(x1[j]);
|
|
285
|
+
};
|
|
286
|
+
};
|
|
287
|
+
#endif
|
|
288
|
+
|
|
289
|
+
#ifdef USE_VML
|
|
290
|
+
typedef void (*FuncBDPtr_vml)(MKL_INT, const double*, bool*);
|
|
291
|
+
FuncBDPtr_vml functions_bd_vml[] = {
|
|
292
|
+
#define FUNC_BD(fop, s, f, f_vml) f_vml,
|
|
293
|
+
#include "functions.hpp"
|
|
294
|
+
#undef FUNC_BD
|
|
295
|
+
};
|
|
296
|
+
#endif
|
|
297
|
+
|
|
298
|
+
typedef bool (*FuncBCPtr)(std::complex<double>*);
|
|
299
|
+
FuncBCPtr functions_bc[] = {
|
|
300
|
+
#define FUNC_BC(fop, s, f, ...) f,
|
|
301
|
+
#include "functions.hpp"
|
|
302
|
+
#undef FUNC_BC
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
#ifdef USE_VML
|
|
306
|
+
/* no isnan, isfinite or isinf in VML */
|
|
307
|
+
static void vzIsfinite(MKL_INT n, const MKL_Complex16* x1, bool* dest)
|
|
308
|
+
{
|
|
309
|
+
MKL_INT j;
|
|
310
|
+
for (j=0; j<n; j++) {
|
|
311
|
+
dest[j] = isfinited(x1[j].real) && isfinited(x1[j].imag);
|
|
312
|
+
};
|
|
313
|
+
};
|
|
314
|
+
static void vzIsinf(MKL_INT n, const MKL_Complex16* x1, bool* dest)
|
|
315
|
+
{
|
|
316
|
+
MKL_INT j;
|
|
317
|
+
for (j=0; j<n; j++) {
|
|
318
|
+
dest[j] = isinfd(x1[j].real) || isinfd(x1[j].imag);
|
|
319
|
+
};
|
|
320
|
+
};
|
|
321
|
+
static void vzIsnan(MKL_INT n, const MKL_Complex16* x1, bool* dest)
|
|
322
|
+
{
|
|
323
|
+
MKL_INT j;
|
|
324
|
+
for (j=0; j<n; j++) {
|
|
325
|
+
dest[j] = isnand(x1[j].real) || isnand(x1[j].imag);
|
|
326
|
+
};
|
|
327
|
+
};
|
|
328
|
+
#endif
|
|
329
|
+
|
|
330
|
+
#ifdef USE_VML
|
|
331
|
+
typedef void (*FuncBCPtr_vml)(MKL_INT, const MKL_Complex16[], bool*);
|
|
332
|
+
FuncBCPtr_vml functions_bc_vml[] = {
|
|
333
|
+
#define FUNC_BC(fop, s, f, f_vml) f_vml,
|
|
334
|
+
#include "functions.hpp"
|
|
335
|
+
#undef FUNC_BC
|
|
336
|
+
};
|
|
337
|
+
#endif
|
|
338
|
+
|
|
207
339
|
#ifdef USE_VML
|
|
208
340
|
/* Fake vdConj function just for casting purposes inside numexpr */
|
|
209
341
|
static void vdConj(MKL_INT n, const double* x1, double* dest)
|
|
@@ -312,11 +444,11 @@ FuncCCCPtr functions_ccc[] = {
|
|
|
312
444
|
|
|
313
445
|
char
|
|
314
446
|
get_return_sig(PyObject* program)
|
|
315
|
-
{
|
|
447
|
+
{ // use unsigned chars to match OPCODE table and allow OPCODE > 127
|
|
316
448
|
int sig;
|
|
317
|
-
char last_opcode;
|
|
449
|
+
unsigned char last_opcode;
|
|
318
450
|
Py_ssize_t end = PyBytes_Size(program);
|
|
319
|
-
char *program_str = PyBytes_AS_STRING(program);
|
|
451
|
+
unsigned char *program_str = (unsigned char *)PyBytes_AS_STRING(program);
|
|
320
452
|
|
|
321
453
|
do {
|
|
322
454
|
end -= 4;
|
|
@@ -464,7 +596,26 @@ check_program(NumExprObject *self)
|
|
|
464
596
|
PyErr_Format(PyExc_RuntimeError, "invalid program: funccode out of range (%i) at %i", arg, argloc);
|
|
465
597
|
return -1;
|
|
466
598
|
}
|
|
467
|
-
}
|
|
599
|
+
}
|
|
600
|
+
else if (op == OP_FUNC_BDN) {
|
|
601
|
+
if (arg < 0 || arg >= FUNC_BD_LAST) {
|
|
602
|
+
PyErr_Format(PyExc_RuntimeError, "invalid program: funccode out of range (%i) at %i", arg, argloc);
|
|
603
|
+
return -1;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
else if (op == OP_FUNC_BFN) {
|
|
607
|
+
if (arg < 0 || arg >= FUNC_BF_LAST) {
|
|
608
|
+
PyErr_Format(PyExc_RuntimeError, "invalid program: funccode out of range (%i) at %i", arg, argloc);
|
|
609
|
+
return -1;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
else if (op == OP_FUNC_BCN) {
|
|
613
|
+
if (arg < 0 || arg >= FUNC_BC_LAST) {
|
|
614
|
+
PyErr_Format(PyExc_RuntimeError, "invalid program: funccode out of range (%i) at %i", arg, argloc);
|
|
615
|
+
return -1;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
else if (op >= OP_REDUCTION) {
|
|
468
619
|
;
|
|
469
620
|
} else {
|
|
470
621
|
PyErr_Format(PyExc_RuntimeError, "invalid program: internal checker error processing %i", argloc);
|
|
@@ -18,6 +18,12 @@ enum FuncFFCodes {
|
|
|
18
18
|
#undef FUNC_FF
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
+
enum FuncBFCodes {
|
|
22
|
+
#define FUNC_BF(fop, ...) fop,
|
|
23
|
+
#include "functions.hpp"
|
|
24
|
+
#undef FUNC_BF
|
|
25
|
+
};
|
|
26
|
+
|
|
21
27
|
enum FuncFFFCodes {
|
|
22
28
|
#define FUNC_FFF(fop, ...) fop,
|
|
23
29
|
#include "functions.hpp"
|
|
@@ -30,6 +36,18 @@ enum FuncDDCodes {
|
|
|
30
36
|
#undef FUNC_DD
|
|
31
37
|
};
|
|
32
38
|
|
|
39
|
+
enum FuncBDCodes {
|
|
40
|
+
#define FUNC_BD(fop, ...) fop,
|
|
41
|
+
#include "functions.hpp"
|
|
42
|
+
#undef FUNC_BD
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
enum FuncBCCodes {
|
|
46
|
+
#define FUNC_BC(fop, ...) fop,
|
|
47
|
+
#include "functions.hpp"
|
|
48
|
+
#undef FUNC_BC
|
|
49
|
+
};
|
|
50
|
+
|
|
33
51
|
enum FuncDDDCodes {
|
|
34
52
|
#define FUNC_DDD(fop, ...) fop,
|
|
35
53
|
#include "functions.hpp"
|
|
@@ -506,6 +506,9 @@ PyInit_interpreter(void) {
|
|
|
506
506
|
#define FUNC_FF(name, sname, ...) add_func(name, sname);
|
|
507
507
|
#define FUNC_FFF(name, sname, ...) add_func(name, sname);
|
|
508
508
|
#define FUNC_DD(name, sname, ...) add_func(name, sname);
|
|
509
|
+
#define FUNC_BF(name, sname, ...) add_func(name, sname);
|
|
510
|
+
#define FUNC_BD(name, sname, ...) add_func(name, sname);
|
|
511
|
+
#define FUNC_BC(name, sname, ...) add_func(name, sname);
|
|
509
512
|
#define FUNC_DDD(name, sname, ...) add_func(name, sname);
|
|
510
513
|
#define FUNC_CC(name, sname, ...) add_func(name, sname);
|
|
511
514
|
#define FUNC_CCC(name, sname, ...) add_func(name, sname);
|
|
@@ -513,7 +516,9 @@ PyInit_interpreter(void) {
|
|
|
513
516
|
#undef FUNC_CCC
|
|
514
517
|
#undef FUNC_CC
|
|
515
518
|
#undef FUNC_DDD
|
|
516
|
-
#undef
|
|
519
|
+
#undef FUNC_BC
|
|
520
|
+
#undef FUNC_BD
|
|
521
|
+
#undef FUNC_BF
|
|
517
522
|
#undef FUNC_DD
|
|
518
523
|
#undef FUNC_FFF
|
|
519
524
|
#undef FUNC_FF
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
#include <float.h> // for _finite, _isnan on MSVC
|
|
2
|
+
|
|
1
3
|
#ifndef NUMEXPR_MSVC_FUNCTION_STUBS_HPP
|
|
2
4
|
#define NUMEXPR_MSVC_FUNCTION_STUBS_HPP
|
|
3
5
|
|
|
@@ -43,9 +45,17 @@
|
|
|
43
45
|
/* The next are directly called from interp_body.cpp */
|
|
44
46
|
#define powf(x, y) ((float)pow((double)(x), (double)(y)))
|
|
45
47
|
#define floorf(x) ((float)floor((double)(x)))
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
#endif // _MSC_VER < 1400
|
|
49
|
+
|
|
50
|
+
/* Due to casting problems (normally return ints not bools, easiest to define
|
|
51
|
+
non-overloaded wrappers for these functions) */
|
|
52
|
+
// MSVC version: use global ::isfinite / ::isnan
|
|
53
|
+
inline bool isfinitef_(float x) { return !!::_finite(x); } // MSVC has _finite
|
|
54
|
+
inline bool isnanf_(float x) { return !!::_isnan(x); } // MSVC has _isnan
|
|
55
|
+
inline bool isfinited(double x) { return !!::_finite(x); }
|
|
56
|
+
inline bool isnand(double x) { return !!::_isnan(x); }
|
|
57
|
+
inline bool isinfd(double x) { return !!::isinf(x); }
|
|
58
|
+
inline bool isinff_(float x) { return !!::isinf(x); }
|
|
49
59
|
|
|
50
60
|
/* Now the actual stubs */
|
|
51
61
|
|
|
@@ -133,6 +143,20 @@ inline float atan2f2(float x, float y) {
|
|
|
133
143
|
return atan2f(x, y);
|
|
134
144
|
}
|
|
135
145
|
|
|
146
|
+
// Boolean output functions
|
|
147
|
+
inline bool isnanf2(float x) {
|
|
148
|
+
return isnanf_(x);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
inline bool isfinitef2(float x) {
|
|
152
|
+
return isfinitef_(x);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
inline bool isinff2(float x) {
|
|
156
|
+
return isinff_(x);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
136
160
|
// Needed for allowing the internal casting in numexpr machinery for
|
|
137
161
|
// conjugate operations
|
|
138
162
|
inline float fconjf2(float x) {
|
|
@@ -69,7 +69,10 @@ vml_functions = [
|
|
|
69
69
|
"arctan2",
|
|
70
70
|
"fmod",
|
|
71
71
|
"ceil",
|
|
72
|
-
"floor"
|
|
72
|
+
"floor",
|
|
73
|
+
"isnan",
|
|
74
|
+
"isfinite",
|
|
75
|
+
"isinf",
|
|
73
76
|
]
|
|
74
77
|
|
|
75
78
|
|
|
@@ -520,7 +523,7 @@ def compileThreeAddrForm(program):
|
|
|
520
523
|
return bytes([reg.n])
|
|
521
524
|
|
|
522
525
|
def quadrupleToString(opcode, store, a1=None, a2=None):
|
|
523
|
-
cop = chr(interpreter.opcodes[opcode]).encode('
|
|
526
|
+
cop = chr(interpreter.opcodes[opcode]).encode('latin_1')
|
|
524
527
|
cs = nToChr(store)
|
|
525
528
|
ca1 = nToChr(a1)
|
|
526
529
|
ca2 = nToChr(a2)
|
|
@@ -904,7 +907,7 @@ def evaluate(ex: str,
|
|
|
904
907
|
global_dict: Optional[Dict] = None,
|
|
905
908
|
out: numpy.ndarray = None,
|
|
906
909
|
order: str = 'K',
|
|
907
|
-
casting: str = '
|
|
910
|
+
casting: str = 'same_kind',
|
|
908
911
|
sanitize: Optional[bool] = None,
|
|
909
912
|
_frame_depth: int = 3,
|
|
910
913
|
**kwargs) -> numpy.ndarray:
|
|
@@ -46,6 +46,17 @@
|
|
|
46
46
|
#include "missing_posix_functions.hpp"
|
|
47
47
|
#endif
|
|
48
48
|
#include "msvc_function_stubs.hpp"
|
|
49
|
+
#else
|
|
50
|
+
/* GCC/Clang version: use std:: (can't use it for windows)
|
|
51
|
+
msvc_function_stubs contains windows alternatives
|
|
52
|
+
/* Due to casting problems (normally return ints not bools, easiest to define
|
|
53
|
+
non-overloaded wrappers for these functions) */
|
|
54
|
+
inline bool isfinitef_(float x) { return !!::isfinite(x); }
|
|
55
|
+
inline bool isnanf_(float x) { return !!::isnan(x); }
|
|
56
|
+
inline bool isfinited(double x) { return !!::isfinite(x); }
|
|
57
|
+
inline bool isnand(double x) { return !!::isnan(x); }
|
|
58
|
+
inline bool isinff_(float x) { return !!::isinf(x); }
|
|
59
|
+
inline bool isinfd(double x) { return !!::isinf(x); }
|
|
49
60
|
#endif
|
|
50
61
|
|
|
51
62
|
#endif // NUMEXPR_CONFIG_HPP
|
|
@@ -15,6 +15,9 @@ OPCODE(n, enum_name, exported, return_type, arg1_type, arg2_type, arg3_type)
|
|
|
15
15
|
Types are Tb, Ti, Tl, Tf, Td, Tc, Ts, Tn, and T0; these symbols should be
|
|
16
16
|
#defined to whatever is needed. (T0 is the no-such-arg type.)
|
|
17
17
|
|
|
18
|
+
When adding new OPCODES, one has to respect the order of the numeration, as
|
|
19
|
+
there are parts of the code (iterations) which assume that the OPCODES are ordered.
|
|
20
|
+
|
|
18
21
|
*/
|
|
19
22
|
OPCODE(0, OP_NOOP, "noop", T0, T0, T0, T0)
|
|
20
23
|
|
|
@@ -144,36 +147,47 @@ OPCODE(103, OP_COPY_SS, "copy_ss", Ts, Ts, T0, T0)
|
|
|
144
147
|
OPCODE(104, OP_WHERE_BBBB, "where_bbbb", Tb, Tb, Tb, Tb)
|
|
145
148
|
|
|
146
149
|
OPCODE(105, OP_CONTAINS_BSS, "contains_bss", Tb, Ts, Ts, T0)
|
|
150
|
+
//Boolean outputs
|
|
151
|
+
OPCODE(106, OP_FUNC_BDN, "func_bdn", Tb, Td, Tn, T0)
|
|
152
|
+
OPCODE(107, OP_FUNC_BFN, "func_bfn", Tb, Tf, Tn, T0)
|
|
153
|
+
OPCODE(108, OP_FUNC_BCN, "func_bcn", Tb, Tc, Tn, T0)
|
|
147
154
|
|
|
148
|
-
|
|
155
|
+
// Reductions always have to be at the end - parts of the code
|
|
156
|
+
// use > OP_REDUCTION to decide whether operation is a reduction
|
|
157
|
+
OPCODE(109, OP_REDUCTION, NULL, T0, T0, T0, T0)
|
|
149
158
|
|
|
150
159
|
/* Last argument in a reduction is the axis of the array the
|
|
151
160
|
reduction should be applied along. */
|
|
152
161
|
|
|
153
|
-
OPCODE(
|
|
154
|
-
OPCODE(
|
|
155
|
-
OPCODE(
|
|
156
|
-
OPCODE(
|
|
157
|
-
OPCODE(
|
|
158
|
-
|
|
159
|
-
OPCODE(
|
|
160
|
-
OPCODE(
|
|
161
|
-
OPCODE(
|
|
162
|
-
OPCODE(
|
|
163
|
-
OPCODE(
|
|
164
|
-
OPCODE(
|
|
165
|
-
|
|
166
|
-
OPCODE(
|
|
167
|
-
OPCODE(
|
|
168
|
-
OPCODE(
|
|
169
|
-
OPCODE(
|
|
170
|
-
OPCODE(
|
|
171
|
-
|
|
172
|
-
OPCODE(
|
|
173
|
-
OPCODE(
|
|
174
|
-
OPCODE(
|
|
175
|
-
OPCODE(
|
|
176
|
-
OPCODE(
|
|
162
|
+
OPCODE(110, OP_SUM_IIN, "sum_iin", Ti, Ti, Tn, T0)
|
|
163
|
+
OPCODE(111, OP_SUM_LLN, "sum_lln", Tl, Tl, Tn, T0)
|
|
164
|
+
OPCODE(112, OP_SUM_FFN, "sum_ffn", Tf, Tf, Tn, T0)
|
|
165
|
+
OPCODE(113, OP_SUM_DDN, "sum_ddn", Td, Td, Tn, T0)
|
|
166
|
+
OPCODE(114, OP_SUM_CCN, "sum_ccn", Tc, Tc, Tn, T0)
|
|
167
|
+
|
|
168
|
+
OPCODE(115, OP_PROD, NULL, T0, T0, T0, T0)
|
|
169
|
+
OPCODE(116, OP_PROD_IIN, "prod_iin", Ti, Ti, Tn, T0)
|
|
170
|
+
OPCODE(117, OP_PROD_LLN, "prod_lln", Tl, Tl, Tn, T0)
|
|
171
|
+
OPCODE(118, OP_PROD_FFN, "prod_ffn", Tf, Tf, Tn, T0)
|
|
172
|
+
OPCODE(119, OP_PROD_DDN, "prod_ddn", Td, Td, Tn, T0)
|
|
173
|
+
OPCODE(120, OP_PROD_CCN, "prod_ccn", Tc, Tc, Tn, T0)
|
|
174
|
+
|
|
175
|
+
OPCODE(121, OP_MIN, NULL, T0, T0, T0, T0)
|
|
176
|
+
OPCODE(122, OP_MIN_IIN, "min_iin", Ti, Ti, Tn, T0)
|
|
177
|
+
OPCODE(123, OP_MIN_LLN, "min_lln", Tl, Tl, Tn, T0)
|
|
178
|
+
OPCODE(124, OP_MIN_FFN, "min_ffn", Tf, Tf, Tn, T0)
|
|
179
|
+
OPCODE(125, OP_MIN_DDN, "min_ddn", Td, Td, Tn, T0)
|
|
180
|
+
|
|
181
|
+
OPCODE(126, OP_MAX, NULL, T0, T0, T0, T0)
|
|
182
|
+
OPCODE(127, OP_MAX_IIN, "max_iin", Ti, Ti, Tn, T0)
|
|
183
|
+
OPCODE(128, OP_MAX_LLN, "max_lln", Tl, Tl, Tn, T0)
|
|
184
|
+
OPCODE(129, OP_MAX_FFN, "max_ffn", Tf, Tf, Tn, T0)
|
|
185
|
+
OPCODE(130, OP_MAX_DDN, "max_ddn", Td, Td, Tn, T0)
|
|
177
186
|
|
|
187
|
+
/*
|
|
188
|
+
When we get to 255, will maybe have to change code again
|
|
189
|
+
(change latin_1 encoding in necompiler.py, use something
|
|
190
|
+
other than unsigned char for OPCODE table)
|
|
191
|
+
*/
|
|
178
192
|
/* Should be the last opcode */
|
|
179
|
-
OPCODE(
|
|
193
|
+
OPCODE(131, OP_END, NULL, T0, T0, T0, T0)
|
|
@@ -683,7 +683,6 @@ class test_evaluate(TestCase):
|
|
|
683
683
|
out_l = evaluate('base ** -1.0')
|
|
684
684
|
assert_equal(out_l, np.power(base, -1.0))
|
|
685
685
|
|
|
686
|
-
|
|
687
686
|
def test_ex_uses_vml(self):
|
|
688
687
|
vml_funcs = [ "sin", "cos", "tan", "arcsin", "arccos", "arctan",
|
|
689
688
|
"sinh", "cosh", "tanh", "arcsinh", "arccosh", "arctanh",
|
|
@@ -694,6 +693,28 @@ class test_evaluate(TestCase):
|
|
|
694
693
|
_, ex_uses_vml = numexpr.necompiler.getExprNames(strexpr, {})
|
|
695
694
|
assert_equal(ex_uses_vml, use_vml, strexpr)
|
|
696
695
|
|
|
696
|
+
def test_bool_funcs(self):
|
|
697
|
+
# Test functions with boolean outputs
|
|
698
|
+
array_size = 100
|
|
699
|
+
dtype = np.float32
|
|
700
|
+
a = np.arange(2 * array_size, dtype=dtype)
|
|
701
|
+
a[array_size//2] = np.nan
|
|
702
|
+
a[array_size//3] = np.inf
|
|
703
|
+
|
|
704
|
+
assert np.all(evaluate("isnan(a)") == np.isnan(a))
|
|
705
|
+
assert np.all(evaluate("isfinite(a)") == np.isfinite(a))
|
|
706
|
+
assert np.all(evaluate("isinf(a)") == np.isinf(a))
|
|
707
|
+
a = a.astype(np.float64)
|
|
708
|
+
assert a.dtype == np.float64
|
|
709
|
+
assert np.all(evaluate("isnan(a)") == np.isnan(a))
|
|
710
|
+
assert np.all(evaluate("isfinite(a)") == np.isfinite(a))
|
|
711
|
+
assert np.all(evaluate("isinf(a)") == np.isinf(a))
|
|
712
|
+
a = a.astype(np.complex128)
|
|
713
|
+
assert a.dtype == np.complex128
|
|
714
|
+
assert np.all(evaluate("isnan(a)") == np.isnan(a))
|
|
715
|
+
assert np.all(evaluate("isfinite(a)") == np.isfinite(a))
|
|
716
|
+
assert np.all(evaluate("isinf(a)") == np.isinf(a))
|
|
717
|
+
|
|
697
718
|
if 'sparc' not in platform.machine():
|
|
698
719
|
# Execution order set here so as to not use too many threads
|
|
699
720
|
# during the rest of the execution. See #33 for details.
|
|
@@ -892,7 +913,6 @@ def test_expressions(
|
|
|
892
913
|
npval={npval!r} ({type(npval)!r} - {shape(npval)!r})
|
|
893
914
|
neval={neval!r} ({type(neval)!r} - {shape(neval)!r}))"""
|
|
894
915
|
|
|
895
|
-
|
|
896
916
|
class test_int64(TestCase):
|
|
897
917
|
def test_neg(self):
|
|
898
918
|
a = array([2 ** 31 - 1, 2 ** 31, 2 ** 32, 2 ** 63 - 1], dtype=int64)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: numexpr
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.12.1
|
|
4
4
|
Summary: Fast numerical expression evaluator for NumPy
|
|
5
5
|
Author-email: "David M. Cooke, Francesc Alted, and others" <blosc@blosc.org>
|
|
6
6
|
Maintainer-email: Blosc Development Team <blosc@blosc.org>
|
|
@@ -21,10 +21,11 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
25
|
Requires-Python: >=3.10
|
|
25
26
|
Description-Content-Type: text/x-rst
|
|
26
27
|
License-File: LICENSE.txt
|
|
27
|
-
License-File:
|
|
28
|
+
License-File: LICENSES/cpuinfo.txt
|
|
28
29
|
Requires-Dist: numpy>=1.23.0
|
|
29
30
|
Dynamic: license-file
|
|
30
31
|
|
|
@@ -136,7 +137,7 @@ See `requirements.txt` for the required version of NumPy.
|
|
|
136
137
|
|
|
137
138
|
NumExpr is built in the standard Python way::
|
|
138
139
|
|
|
139
|
-
|
|
140
|
+
pip install [-e] .
|
|
140
141
|
|
|
141
142
|
You can test `numexpr` with::
|
|
142
143
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
[build-system]
|
|
2
2
|
requires = [
|
|
3
|
-
"setuptools",
|
|
4
|
-
"wheel",
|
|
3
|
+
"setuptools>=77.0.0",
|
|
5
4
|
"numpy>=2.0.0",
|
|
6
5
|
]
|
|
7
6
|
build-backend = "setuptools.build_meta"
|
|
@@ -16,6 +15,7 @@ readme = "README.rst"
|
|
|
16
15
|
authors = [{name = "David M. Cooke, Francesc Alted, and others", email = "blosc@blosc.org"}]
|
|
17
16
|
maintainers = [{ name = "Blosc Development Team", email = "blosc@blosc.org"}]
|
|
18
17
|
license = "MIT"
|
|
18
|
+
license-files = ["LICENSE.txt", "LICENSES/*"]
|
|
19
19
|
classifiers = [
|
|
20
20
|
"Development Status :: 6 - Mature",
|
|
21
21
|
"Intended Audience :: Developers",
|
|
@@ -30,6 +30,7 @@ classifiers = [
|
|
|
30
30
|
"Programming Language :: Python :: 3.11",
|
|
31
31
|
"Programming Language :: Python :: 3.12",
|
|
32
32
|
"Programming Language :: Python :: 3.13",
|
|
33
|
+
"Programming Language :: Python :: 3.14",
|
|
33
34
|
]
|
|
34
35
|
requires-python = ">=3.10"
|
|
35
36
|
# Follow guidelines from https://scientific-python.org/specs/spec-0000/
|
|
@@ -43,8 +44,21 @@ homepage = "https://github.com/pydata/numexpr"
|
|
|
43
44
|
documentation = "https://numexpr.readthedocs.io"
|
|
44
45
|
repository = "https://github.com/pydata/numexpr"
|
|
45
46
|
|
|
47
|
+
[dependency-groups]
|
|
48
|
+
test = [
|
|
49
|
+
"pytest>=7.0.0",
|
|
50
|
+
"pytest-run-parallel>=0.6.0",
|
|
51
|
+
]
|
|
52
|
+
|
|
46
53
|
[tool.cibuildwheel]
|
|
47
|
-
|
|
54
|
+
build-verbosity = 1
|
|
55
|
+
skip = ["*-manylinux_i686", "*_ppc64le", "*_s390x"]
|
|
48
56
|
# Let's use a more recent version of the manylinux image for more modern compilers
|
|
49
57
|
manylinux-x86_64-image = "manylinux_2_28"
|
|
50
58
|
manylinux-aarch64-image = "manylinux_2_28"
|
|
59
|
+
test-groups = ["test"]
|
|
60
|
+
test-command = ["python -m pytest --pyargs numexpr"]
|
|
61
|
+
|
|
62
|
+
[[tool.cibuildwheel.overrides]]
|
|
63
|
+
select = "cp31*t-*"
|
|
64
|
+
test-command = ["python -m pytest --parallel-threads=4 --pyargs numexpr"]
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
# file to "site.cfg" and edit the paths according to your installation of the
|
|
3
3
|
# Intel MKL.
|
|
4
4
|
|
|
5
|
-
# Example for Intel(R) MKL
|
|
5
|
+
# Example for Intel(R) OneAPI MKL 2025 on Linux
|
|
6
|
+
# When compiling (with e.g. `pip install -e. -v`), first do a:
|
|
7
|
+
# $ source /opt/intel/oneapi/setvars.sh >/dev/null 2>&1 || true
|
|
6
8
|
# [mkl]
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
+
# include_dirs = /opt/intel/oneapi/mkl/latest/include
|
|
10
|
+
# library_dirs = /opt/intel/oneapi/mkl/latest/lib/intel64
|
|
9
11
|
# libraries = mkl_rt
|
|
10
12
|
|
|
11
13
|
|
numexpr-2.11.0/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.11.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|