4747
4848
4949def compute_slice_shape (shape , slice_obj , dont_squeeze = False ): # noqa: C901
50- """
51- Compute the shape of an array after applying a slice.
52-
53- Parameters
54- ----------
55- shape : tuple
56- The original shape of the array.
57- slice_obj : int, slice, tuple of slices, or None
58- The slice object to apply to the array.
59- dont_squeeze : bool
60- Integer indexing normall reduces dimensionality. Setting this
61- to True, makes dimensionality untouched.
62-
63- Returns
64- -------
65- slice_shape : tuple
66- The shape of the resulting array after applying the slice.
67- """
6850 # Handle None or empty slice case
6951 if slice_obj is None or slice_obj == ():
7052 return shape
7153
7254 # Use ndindex to handle slice calculations
7355 try :
74- # ndindex.ndindex converts slice_obj to a standardized form
75- # and expand expands it to match the shape of the array
7656 idx = ndindex .ndindex (slice_obj ).expand (shape )
77- # Use ndindex's shape property which calculates the resulting shape
7857 return idx .shape
7958 except Exception :
80- # Fall back to manual processing if ndindex fails
81- # This could happen for complex cases that ndindex doesn't handle well
59+ # Fall back to manual processing
8260 if not isinstance (slice_obj , tuple ):
8361 slice_obj = (slice_obj ,)
8462
8563 result = []
8664 shape_idx = 0
65+ dims_reduced = 0
8766
8867 # Process slice components
8968 for i , s in enumerate (slice_obj ):
@@ -103,21 +82,23 @@ def compute_slice_shape(shape, slice_obj, dont_squeeze=False): # noqa: C901
10382 result .append ((stop - start - 1 ) // step + 1 )
10483 else :
10584 result .append (0 )
85+ shape_idx += 1
10686 elif isinstance (s , int ) or np .isscalar (s ):
10787 if dont_squeeze :
10888 result .append (1 )
89+ shape_idx += 1
10990 else :
110- # Integer indexing reduces dimensionality (normally)
91+ # Integer indexing reduces dimensionality
92+ dims_reduced += 1
93+ shape_idx += 1
11194 continue
11295 elif s is Ellipsis :
11396 # Fill in with remaining dimensions
114- remaining_dims = len (shape ) - (len (slice_obj ) - 1 )
97+ remaining_dims = len (shape ) - (len (slice_obj ) - 1 + dims_reduced )
11598 result .extend (shape [shape_idx : shape_idx + remaining_dims ])
11699 shape_idx += remaining_dims
117100 continue
118101
119- shape_idx += 1
120-
121102 # Add any remaining dimensions
122103 if shape_idx < len (shape ):
123104 result .extend (shape [shape_idx :])
@@ -2050,11 +2031,16 @@ def chunked_eval( # noqa: C901
20502031 return reduce_slices (expression , operands , reduce_args = reduce_args , _slice = item , ** kwargs )
20512032
20522033 if not is_full_slice (item ) or (where is not None and len (where ) < 2 ):
2053- # The fast path is not possible when using partial slices or where returning
2054- # a variable number of elements
2034+ # The fast path is possible under a few conditions
20552035 if getitem and (where is None or len (where ) == 2 ) and not callable (expression ):
2056- # If we are using getitem, we can still use some optimizations
2057- return slices_eval_getitem (expression , operands , _slice = item , ** kwargs )
2036+ # Compute the size of operands for the fast path
2037+ shape = compute_broadcast_shape (operands .values ())
2038+ shape_operands = compute_slice_shape (shape , item )
2039+ _dtype = kwargs .get ("dtype" , np .float64 )
2040+ size_operands = math .prod (shape_operands ) * len (operands ) * _dtype .itemsize
2041+ # Only take the fast path if the size of operands is relatively small
2042+ if size_operands < blosc2 .MAX_FAST_PATH_SIZE :
2043+ return slices_eval_getitem (expression , operands , _slice = item , ** kwargs )
20582044 return slices_eval (expression , operands , getitem = getitem , _slice = item , ** kwargs )
20592045
20602046 if fast_path :
0 commit comments