Skip to content

Commit 87d211d

Browse files
committed
Minimal changes for enabling miniexpr for windows
1 parent 613d211 commit 87d211d

3 files changed

Lines changed: 44 additions & 6 deletions

File tree

RELEASE_NOTES.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
## Changes from 4.0.0-b1 to 4.0.0-b2
44

5-
XXX version-specific blurb XXX
5+
- On Windows, miniexpr is temporarily disabled for integral outputs and mixed-dtype expressions.
6+
Set `BLOSC2_ENABLE_MINIEXPR_WINDOWS=1` to override this for testing.
67

78
## Changes from 3.12.2 to 4.0.0-b1
89

src/blosc2/blosc2_ext.pyx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,7 @@ cdef int aux_miniexpr(me_udata *udata, int64_t nchunk, int32_t nblock,
19471947
memset(params_output, 0, udata.array.blocknitems * typesize)
19481948
free(input_buffers)
19491949
return 0
1950+
19501951
for i in range(udata.ninputs):
19511952
ndarr = udata.inputs[i]
19521953
input_buffers[i] = malloc(ndarr.sc.blocksize)
@@ -2013,14 +2014,19 @@ cdef int aux_miniexpr(me_udata *udata, int64_t nchunk, int32_t nblock,
20132014
cdef uintptr_t offset_bytes = typesize * linear_block_index
20142015

20152016
# Call thread-safe miniexpr C API
2017+
# NOTE: me_eval_nd expects the OUTPUT block size (in items), not the input block size.
2018+
# For element-wise operations with same dtypes, they're equal, but for type-changing
2019+
# operations (e.g., arccos(int32) -> float64), we must use the output's block item count.
2020+
cdef int output_blocknitems = udata.array.blocknitems
2021+
20162022
if udata.aux_reduc_ptr == NULL:
20172023
aux_reduc_ptr = <void *> params_output
20182024
else:
20192025
# Reduction operation: evaluate only valid items into a single output element.
20202026
# NOTE: miniexpr handles scalar outputs in me_eval_nd without touching tail bytes.
20212027
aux_reduc_ptr = <void *> (<uintptr_t> udata.aux_reduc_ptr + offset_bytes)
20222028
rc = me_eval_nd(miniexpr_handle, <const void**> input_buffers, udata.ninputs,
2023-
aux_reduc_ptr, blocknitems, nchunk, nblock, udata.eval_params)
2029+
aux_reduc_ptr, output_blocknitems, nchunk, nblock, udata.eval_params)
20242030
if rc != 0:
20252031
raise RuntimeError(f"miniexpr: issues during evaluation; error code: {rc}")
20262032

src/blosc2/lazyexpr.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,9 @@
9595
try_miniexpr = True
9696
if blosc2.IS_WASM:
9797
try_miniexpr = False
98-
if sys.platform == "win32":
99-
# Although miniexpr has support for windows, the integration with Blosc2
100-
# still has some rough edges.
101-
try_miniexpr = False
98+
99+
_MINIEXPR_WINDOWS_OVERRIDE = os.environ.get("BLOSC2_ENABLE_MINIEXPR_WINDOWS", "").strip().lower()
100+
_MINIEXPR_WINDOWS_OVERRIDE = _MINIEXPR_WINDOWS_OVERRIDE not in ("", "0", "false", "no", "off")
102101

103102

104103
def ne_evaluate(expression, local_dict=None, **kwargs):
@@ -1326,6 +1325,26 @@ def fast_eval( # noqa: C901
13261325
use_miniexpr = False
13271326
if not (all_ndarray and out is None):
13281327
use_miniexpr = False
1328+
has_complex = any(
1329+
isinstance(op, blosc2.NDArray) and blosc2.isdtype(op.dtype, "complex floating")
1330+
for op in operands.values()
1331+
)
1332+
if isinstance(expression, str) and has_complex:
1333+
if sys.platform == "win32":
1334+
# On Windows, miniexpr has issues with complex numbers
1335+
use_miniexpr = False
1336+
if any(tok in expression for tok in ("!=", "==", "<=", ">=", "<", ">")):
1337+
use_miniexpr = False
1338+
if sys.platform == "win32" and use_miniexpr and not _MINIEXPR_WINDOWS_OVERRIDE:
1339+
# Work around Windows miniexpr issues for integer outputs and dtype conversions.
1340+
if blosc2.isdtype(dtype, "integral"):
1341+
use_miniexpr = False
1342+
else:
1343+
dtype_mismatch = any(
1344+
isinstance(op, blosc2.NDArray) and op.dtype != dtype for op in operands.values()
1345+
)
1346+
if dtype_mismatch:
1347+
use_miniexpr = False
13291348

13301349
if use_miniexpr:
13311350
cparams = kwargs.pop("cparams", blosc2.CParams())
@@ -2036,6 +2055,18 @@ def reduce_slices( # noqa: C901
20362055
isinstance(op, blosc2.NDArray) and blosc2.isdtype(op.dtype, "complex floating")
20372056
for op in operands.values()
20382057
)
2058+
if has_complex and sys.platform == "win32":
2059+
# On Windows, miniexpr has issues with complex numbers
2060+
use_miniexpr = False
2061+
if sys.platform == "win32" and use_miniexpr and not _MINIEXPR_WINDOWS_OVERRIDE:
2062+
if blosc2.isdtype(dtype, "integral"):
2063+
use_miniexpr = False
2064+
else:
2065+
dtype_mismatch = any(
2066+
isinstance(op, blosc2.NDArray) and op.dtype != dtype for op in operands.values()
2067+
)
2068+
if dtype_mismatch:
2069+
use_miniexpr = False
20392070
if has_complex and any(tok in expression for tok in ("!=", "==", "<=", ">=", "<", ">")):
20402071
use_miniexpr = False
20412072
if where is not None and len(where) != 2:

0 commit comments

Comments
 (0)