Skip to content

Commit 2fd4c71

Browse files
committed
Fix for reductions in miniexpr (depends on reduc type)
1 parent e9b1c80 commit 2fd4c71

2 files changed

Lines changed: 24 additions & 4 deletions

File tree

src/blosc2/blosc2_ext.pyx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,8 +1925,11 @@ cdef int aux_miniexpr(me_udata *udata, int64_t nchunk, int32_t nblock,
19251925

19261926
cdef me_expr* miniexpr_handle = udata.miniexpr_handle
19271927
cdef void* aux_reduc_ptr
1928-
# Calculate blocks per chunk using CEILING division (chunks are padded to fit whole blocks)
1929-
cdef int nblocks_per_chunk = (udata.array.chunknitems + udata.array.blocknitems - 1) // udata.array.blocknitems
1928+
# For reduction operations, we need to track which block we're processing
1929+
# The linear_block_index should be based on the INPUT array structure, not the output array
1930+
# Get the first input array's chunk and block structure
1931+
cdef b2nd_array_t* first_input = udata.inputs[0]
1932+
cdef int nblocks_per_chunk = (first_input.chunknitems + first_input.blocknitems - 1) // first_input.blocknitems
19301933
# Calculate the global linear block index: nchunk * blocks_per_chunk + nblock
19311934
# This works because blocks never span chunks (chunks are padded to block boundaries)
19321935
cdef int64_t linear_block_index = nchunk * nblocks_per_chunk + nblock

src/blosc2/lazyexpr.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,8 +2031,25 @@ def reduce_slices( # noqa: C901
20312031
res_eval = blosc2.uninit(shape, dtype, chunks=chunks, blocks=blocks, cparams=cparams, **kwargs)
20322032
# Compute the number of blocks in the result
20332033
nblocks = res_eval.nbytes // res_eval.blocksize
2034-
# Initialize to zeros since some blocks may be padding and won't be written
2035-
aux_reduc = np.zeros(nblocks, dtype=dtype)
2034+
# Initialize aux_reduc based on the reduction operation
2035+
# Padding blocks won't be written, so initial values matter for the final reduction
2036+
if reduce_op == ReduceOp.SUM or reduce_op == ReduceOp.ANY:
2037+
aux_reduc = np.zeros(nblocks, dtype=dtype)
2038+
elif reduce_op == ReduceOp.PROD or reduce_op == ReduceOp.ALL:
2039+
aux_reduc = np.ones(nblocks, dtype=dtype)
2040+
elif reduce_op == ReduceOp.MIN:
2041+
if np.issubdtype(dtype, np.integer):
2042+
aux_reduc = np.full(nblocks, np.iinfo(dtype).max, dtype=dtype)
2043+
else:
2044+
aux_reduc = np.full(nblocks, np.inf, dtype=dtype)
2045+
elif reduce_op == ReduceOp.MAX:
2046+
if np.issubdtype(dtype, np.integer):
2047+
aux_reduc = np.full(nblocks, np.iinfo(dtype).min, dtype=dtype)
2048+
else:
2049+
aux_reduc = np.full(nblocks, -np.inf, dtype=dtype)
2050+
else:
2051+
# For other operations, zeros should be safe
2052+
aux_reduc = np.zeros(nblocks, dtype=dtype)
20362053
try:
20372054
print("expr->miniexpr:", expression, reduce_op)
20382055
expression = f"{reduce_op_str}({expression})"

0 commit comments

Comments
 (0)