@@ -1201,8 +1201,7 @@ def fast_eval( # noqa: C901
12011201
12021202 chunk_operands = {}
12031203 # Check which chunks intersect with _slice
1204- chunk_size = ndindex .ChunkSize (chunks )
1205- all_chunks = chunk_size .as_subchunks ((), shape ) # if _slice is (), returns all chunks
1204+ all_chunks = get_intersecting_chunks ((), shape , chunks ) # if _slice is (), returns all chunks
12061205 for nchunk , chunk_slice in enumerate (all_chunks ):
12071206 cslice = chunk_slice .raw
12081207 offset = tuple (s .start for s in cslice ) # offset for the udf
@@ -1404,9 +1403,10 @@ def slices_eval( # noqa: C901
14041403
14051404 # Iterate over the operands and get the chunks
14061405 chunk_operands = {}
1407- # Check which chunks intersect with _slice
1408- chunk_size = ndindex .ChunkSize (chunks )
1409- intersecting_chunks = chunk_size .as_subchunks (_slice , shape ) # if _slice is (), returns all chunks
1406+ # Check which chunks intersect with _slice (handles zero chunks internally)
1407+ intersecting_chunks = get_intersecting_chunks (
1408+ _slice , shape , chunks
1409+ ) # if _slice is (), returns all chunks
14101410
14111411 for nchunk , chunk_slice in enumerate (intersecting_chunks ):
14121412 # get intersection of chunk and target
@@ -1790,7 +1790,7 @@ def reduce_slices( # noqa: C901
17901790 same_shape = all (operand .shape == o .shape for o in operands .values () if hasattr (o , "shape" ))
17911791 same_chunks = all (operand .chunks == o .chunks for o in operands .values () if hasattr (o , "chunks" ))
17921792 same_blocks = all (operand .blocks == o .blocks for o in operands .values () if hasattr (o , "blocks" ))
1793- fast_path = same_shape and same_chunks and same_blocks
1793+ fast_path = same_shape and same_chunks and same_blocks and ( 0 not in chunks )
17941794 aligned , iter_disk = False , False
17951795 if fast_path :
17961796 # Check that all operands are NDArray for fast path
@@ -1824,8 +1824,8 @@ def reduce_slices( # noqa: C901
18241824 # Iterate over the operands and get the chunks
18251825 chunk_operands = {}
18261826 # Check which chunks intersect with _slice
1827- chunk_size = ndindex . ChunkSize ( chunks )
1828- intersecting_chunks = chunk_size . as_subchunks (_slice , shape ) # if _slice is (), returns all chunks
1827+ # if chunks has 0 we loop once but fast path is false as gives error (schunk has no chunks)
1828+ intersecting_chunks = get_intersecting_chunks (_slice , shape , chunks )
18291829 out_init = False
18301830
18311831 for nchunk , chunk_slice in enumerate (intersecting_chunks ):
@@ -2882,7 +2882,7 @@ def sort(self, order: str | list[str] | None = None) -> blosc2.LazyArray:
28822882 lazy_expr ._order = order
28832883 return lazy_expr
28842884
2885- def compute (self , item = (), ** kwargs ) -> blosc2 .NDArray : # noqa : C901
2885+ def compute (self , item = (), ** kwargs ) -> blosc2 .NDArray :
28862886 # When NumPy ufuncs are called, the user may add an `out` parameter to kwargs
28872887 if "out" in kwargs :
28882888 kwargs ["_output" ] = kwargs .pop ("out" )
@@ -2900,14 +2900,7 @@ def compute(self, item=(), **kwargs) -> blosc2.NDArray: # noqa : C901
29002900 if hasattr (self , "_order" ):
29012901 kwargs ["_order" ] = self ._order
29022902 # handle empty arrays
2903- if 0 in self .shape :
2904- result = (
2905- np .empty (self .shape , dtype = self .dtype )
2906- if "_getitem" in kwargs
2907- else blosc2 .empty (self .shape , dtype = self .dtype )
2908- )
2909- else :
2910- result = self ._compute_expr (item , kwargs )
2903+ result = self ._compute_expr (item , kwargs )
29112904 if "_order" in kwargs and "_indices" not in kwargs :
29122905 # We still need to apply the index in result
29132906 x = self ._where_args ["_where_x" ]
@@ -3618,6 +3611,16 @@ def evaluate(
36183611 return lexpr [()]
36193612
36203613
3614+ def get_intersecting_chunks (_slice , shape , chunks ):
3615+ if 0 not in chunks :
3616+ chunk_size = ndindex .ChunkSize (chunks )
3617+ return chunk_size .as_subchunks (_slice , shape ) # if _slice is (), returns all chunks
3618+ else :
3619+ return (
3620+ ndindex .ndindex (...).expand (shape ),
3621+ ) # chunk is whole array so just return full tuple to do loop once
3622+
3623+
36213624if __name__ == "__main__" :
36223625 from time import time
36233626
0 commit comments