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.
Files changed (61) hide show
  1. numexpr-2.12.1/ADDFUNCS.rst +241 -0
  2. {numexpr-2.11.0 → numexpr-2.12.1}/ANNOUNCE.rst +10 -16
  3. numexpr-2.12.1/LICENSES/cpuinfo.txt +31 -0
  4. {numexpr-2.11.0 → numexpr-2.12.1}/PKG-INFO +4 -3
  5. {numexpr-2.11.0 → numexpr-2.12.1}/README.rst +1 -1
  6. {numexpr-2.11.0 → numexpr-2.12.1}/RELEASE_NOTES.rst +28 -1
  7. numexpr-2.12.1/VERSION +1 -0
  8. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/complex_functions.hpp +29 -0
  9. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/expressions.py +6 -0
  10. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/functions.hpp +42 -0
  11. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/interp_body.cpp +29 -0
  12. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/interpreter.cpp +155 -4
  13. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/interpreter.hpp +18 -0
  14. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/module.cpp +6 -1
  15. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/msvc_function_stubs.hpp +27 -3
  16. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/necompiler.py +6 -3
  17. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/numexpr_config.hpp +11 -0
  18. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/opcodes.hpp +40 -26
  19. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/tests/conftest.py +1 -0
  20. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/tests/test_numexpr.py +22 -2
  21. numexpr-2.12.1/numexpr/version.py +5 -0
  22. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr.egg-info/PKG-INFO +4 -3
  23. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr.egg-info/SOURCES.txt +2 -0
  24. {numexpr-2.11.0 → numexpr-2.12.1}/pyproject.toml +17 -3
  25. {numexpr-2.11.0 → numexpr-2.12.1}/site.cfg.example +5 -3
  26. numexpr-2.11.0/VERSION +0 -1
  27. numexpr-2.11.0/numexpr/version.py +0 -5
  28. {numexpr-2.11.0 → numexpr-2.12.1}/AUTHORS.txt +0 -0
  29. {numexpr-2.11.0 → numexpr-2.12.1}/LICENSE.txt +0 -0
  30. {numexpr-2.11.0 → numexpr-2.12.1}/MANIFEST.in +0 -0
  31. {numexpr-2.11.0 → numexpr-2.12.1}/bench/boolean_timing.py +0 -0
  32. {numexpr-2.11.0 → numexpr-2.12.1}/bench/free_threading.py +0 -0
  33. {numexpr-2.11.0 → numexpr-2.12.1}/bench/issue-36.py +0 -0
  34. {numexpr-2.11.0 → numexpr-2.12.1}/bench/issue-47.py +0 -0
  35. {numexpr-2.11.0 → numexpr-2.12.1}/bench/large_array_vs_numpy.py +0 -0
  36. {numexpr-2.11.0 → numexpr-2.12.1}/bench/multidim.py +0 -0
  37. {numexpr-2.11.0 → numexpr-2.12.1}/bench/poly.py +0 -0
  38. {numexpr-2.11.0 → numexpr-2.12.1}/bench/timing.py +0 -0
  39. {numexpr-2.11.0 → numexpr-2.12.1}/bench/unaligned-simple.py +0 -0
  40. {numexpr-2.11.0 → numexpr-2.12.1}/bench/varying-expr.py +0 -0
  41. {numexpr-2.11.0 → numexpr-2.12.1}/bench/vml_timing.py +0 -0
  42. {numexpr-2.11.0 → numexpr-2.12.1}/bench/vml_timing2.py +0 -0
  43. {numexpr-2.11.0 → numexpr-2.12.1}/bench/vml_timing3.py +0 -0
  44. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/__init__.py +0 -0
  45. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/cpuinfo.py +0 -0
  46. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/missing_posix_functions.hpp +0 -0
  47. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/module.hpp +0 -0
  48. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/numexpr_object.cpp +0 -0
  49. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/numexpr_object.hpp +0 -0
  50. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/str-two-way.hpp +0 -0
  51. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/tests/__init__.py +0 -0
  52. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/utils.py +0 -0
  53. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/win32/pthread.c +0 -0
  54. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/win32/pthread.h +0 -0
  55. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr/win32/stdint.h +0 -0
  56. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr.egg-info/dependency_links.txt +0 -0
  57. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr.egg-info/requires.txt +0 -0
  58. {numexpr-2.11.0 → numexpr-2.12.1}/numexpr.egg-info/top_level.txt +0 -0
  59. {numexpr-2.11.0 → numexpr-2.12.1}/requirements.txt +0 -0
  60. {numexpr-2.11.0 → numexpr-2.12.1}/setup.cfg +0 -0
  61. {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.11.0
2
+ Announcing NumExpr 2.12.1
3
3
  =========================
4
4
 
5
5
  Hi everyone,
6
6
 
7
- NumExpr 2.11.0 Initial support for free-threaded Python 3.13t has been added.
8
- This is still experimental, so please report any issues you find.
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.10.2 to 2.11.0
14
+ Changes from 2.12.0 to 2.12.1
16
15
  -----------------------------
17
16
 
18
- * Initial support for free-threaded Python 3.13t has been added.
19
- This is still experimental, so please report any issues you find.
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
- * Fix imaginary evaluation in the form of `1.1e1j`. This was
24
- previously not supported and would raise an error. Thanks to @27rabbitlt
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
- * The test suite has been modernized to use `pytest` instead of `unittest`.
28
- This should make it easier to run the tests and contribute to the project.
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.11.0
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: AUTHORS.txt
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
- python setup.py build install
140
+ pip install [-e] .
140
141
 
141
142
  You can test `numexpr` with::
142
143
 
@@ -106,7 +106,7 @@ See `requirements.txt` for the required version of NumPy.
106
106
 
107
107
  NumExpr is built in the standard Python way::
108
108
 
109
- python setup.py build install
109
+ pip install [-e] .
110
110
 
111
111
  You can test `numexpr` with::
112
112
 
@@ -1,7 +1,33 @@
1
1
  =====================================
2
- Release notes for NumExpr 2.11 series
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
- } else if (op >= OP_REDUCTION) {
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 FUNC_DD
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
- #endif // _MSC_VER < 1400
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('ascii')
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 = 'safe',
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
- OPCODE(106, OP_REDUCTION, NULL, T0, T0, T0, T0)
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(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)
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(128, OP_END, NULL, T0, T0, T0, T0)
193
+ OPCODE(131, OP_END, NULL, T0, T0, T0, T0)
@@ -10,6 +10,7 @@
10
10
 
11
11
  import pytest
12
12
 
13
+
13
14
  def pytest_configure(config):
14
15
  config.addinivalue_line(
15
16
  "markers", "thread_unsafe: mark test as unsafe for parallel execution"
@@ -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)
@@ -0,0 +1,5 @@
1
+ # THIS FILE IS GENERATED BY `setup.py`
2
+ __version__ = '2.12.1'
3
+ version = '2.12.1'
4
+ numpy_build_version = '2.3.3'
5
+ platform_machine = 'AMD64'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: numexpr
3
- Version: 2.11.0
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: AUTHORS.txt
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
- python setup.py build install
140
+ pip install [-e] .
140
141
 
141
142
  You can test `numexpr` with::
142
143
 
@@ -1,3 +1,4 @@
1
+ ADDFUNCS.rst
1
2
  ANNOUNCE.rst
2
3
  AUTHORS.txt
3
4
  LICENSE.txt
@@ -9,6 +10,7 @@ pyproject.toml
9
10
  requirements.txt
10
11
  setup.py
11
12
  site.cfg.example
13
+ LICENSES/cpuinfo.txt
12
14
  bench/boolean_timing.py
13
15
  bench/free_threading.py
14
16
  bench/issue-36.py
@@ -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
- skip = "cp36-* cp37-* pp37-* cp38-* pp* *-manylinux_i686 *_ppc64le *_s390x"
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 2018 on Linux
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
- # library_dirs = /opt/intel/compilers_and_libraries_2018/linux/mkl/lib/intel64
8
- # include_dirs = /opt/intel/compilers_and_libraries_2018/linux/mkl/include
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
@@ -1,5 +0,0 @@
1
- # THIS FILE IS GENERATED BY `setup.py`
2
- __version__ = '2.11.0'
3
- version = '2.11.0'
4
- numpy_build_version = '2.3.0'
5
- platform_machine = 'AMD64'
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