Repository: scipy/scipy
File: scipy/ndimage/_filters.py (Python)

Code before:
    if rank == 0:
        return minimum_filter(input, None, footprint, output, mode, cval,
                              origins, axes=None)
    elif rank == filter_size - 1:
        return maximum_filter(input, None, footprint, output, mode, cval,
                              origins, axes=None)
    else:
        output = _ni_support._get_output(output, input)
        temp_needed = np.may_share_memory(input, output)
        if temp_needed:
            # input and output arrays cannot share memory
            temp = output
            output = _ni_support._get_output(output.dtype, input)
        if not isinstance(mode, str) and isinstance(mode, Iterable):
            raise RuntimeError(
                "A sequence of modes is not supported by non-separable rank "
                "filters")
        mode = _ni_support._extend_mode_to_code(mode, is_filter=True)
        lim2 = input.size - ((footprint.size - 1) // 2 - origin)
        if input.ndim == 1 and ((lim2 >= 0) or (input.size == 1)):
            if input.dtype in (np.int64, np.float64, np.float32):
                x = input
                x_out = output
            elif input.dtype == np.float16:
                x = input.astype('float32')
                x_out = np.empty(x.shape, dtype='float32')
            elif np.result_type(input, np.int64) == np.int64:
                x = input.astype('int64')
                x_out = np.empty(x.shape, dtype='int64')
            elif input.dtype.kind in 'biu':
                # cast any other boolean, integer or unsigned type to int64
                x = input.astype('int64')
                x_out = np.empty(x.shape, dtype='int64')
            else:
                raise RuntimeError('Unsupported array type')
            cval = x.dtype.type(cval)
            _rank_filter_1d.rank_filter(x, rank, footprint.size, x_out, mode, cval,
                                        origin)
            if input.dtype not in (np.int64, np.float64, np.float32):
                np.copyto(output, x_out, casting='unsafe')
        else:
            _nd_image.rank_filter(input, rank, footprint, output, mode, cval, origins)
        if temp_needed:
            temp[...] = output
            output = temp
        return output


@_ni_docstrings.docfiller
def rank_filter(input, rank, size=None, footprint=None, output=None,
                mode="reflect", cval=0.0, origin=0, *, axes=None):

Review comment (suggestion):
So the fix is that for the corner case of `footprint` being large compared to array size, we're skipping this branch and therefore hitting the old `_nd_image.rank_filter` C implementation rather than the new `_rank_filter_1d.rank_filter` C++ code?

I think that deserves a comment here, because future readers will wonder why the 1-D specific implementation isn't being used for `input.ndim == 1`.

Code after:
    if rank == 0:
        return minimum_filter(input, None, footprint, output, mode, cval,
                              origins, axes=None)
    elif rank == filter_size - 1:
        return maximum_filter(input, None, footprint, output, mode, cval,
                              origins, axes=None)
    else:
        output = _ni_support._get_output(output, input)
        temp_needed = np.may_share_memory(input, output)
        if temp_needed:
            # input and output arrays cannot share memory
            temp = output
            output = _ni_support._get_output(output.dtype, input)
        if not isinstance(mode, str) and isinstance(mode, Iterable):
            raise RuntimeError(
                "A sequence of modes is not supported by non-separable rank "
                "filters")
        mode = _ni_support._extend_mode_to_code(mode, is_filter=True)
        # Some corner cases are currently not allowed to use the
        # "new"/fast 1D rank filter code, including when the
        # footprint is large compared to the array size.
        # See discussion in gh-23293; longer-term it may be possible
        # to allow the fast path for these corner cases as well,
        # if algorithmic fixes are found.
        lim2 = input.size - ((footprint.size - 1) // 2 - origin)
        if input.ndim == 1 and ((lim2 >= 0) or (input.size == 1)):
            if input.dtype in (np.int64, np.float64, np.float32):
                x = input
                x_out = output
            elif input.dtype == np.float16:
                x = input.astype('float32')
                x_out = np.empty(x.shape, dtype='float32')
            elif np.result_type(input, np.int64) == np.int64:
                x = input.astype('int64')
                x_out = np.empty(x.shape, dtype='int64')
            elif input.dtype.kind in 'biu':
                # cast any other boolean, integer or unsigned type to int64
                x = input.astype('int64')
                x_out = np.empty(x.shape, dtype='int64')
            else:
                raise RuntimeError('Unsupported array type')
            cval = x.dtype.type(cval)
            _rank_filter_1d.rank_filter(x, rank, footprint.size, x_out, mode, cval,
                                        origin)
            if input.dtype not in (np.int64, np.float64, np.float32):
                np.copyto(output, x_out, casting='unsafe')
        else:
            _nd_image.rank_filter(input, rank, footprint, output, mode, cval, origins)
        if temp_needed:
            temp[...] = output
            output = temp