//  [python]
def uniform_filter1d_with_conditionals_gpu(
    image, output, current_size, axis, parallelism=None
):
    if image.ndim == 1:
        raise Exception("numba gpu implementation is no supporting 1D input arrays.")
    elif image.ndim == 2:
        axes = list(range(image.ndim))
        axes.remove(axis)
        first_axis_index = axes[0]
        length1 = numpy.prod(image.shape[first_axis_index + 1 :])
        step_size = numpy.prod(image.shape[axis + 1 :])

        threadsperblock = 32 * 32
        blockspergrid = int(math.ceil(image.shape[first_axis_index] / threadsperblock))

        # In some cases if the image is too small, better have more blocks and less threads per block:
        if blockspergrid < 256:
            threadsperblock = 1
            blockspergrid = int(
                math.ceil(image.shape[first_axis_index] / threadsperblock)
            )

        gpu_line_filter_2d[blockspergrid, threadsperblock](
            image.ravel(),
            output.ravel(),
            current_size,
            image.shape[axis],
            length1,
            step_size,
            image.shape[first_axis_index],
        )
    elif image.ndim == 3:
        axes = list(range(image.ndim))
        axes.remove(axis)
        first_axis_index, second_axis_index = tuple(axes)
        length1 = numpy.prod(image.shape[first_axis_index + 1 :])
        length2 = numpy.prod(image.shape[second_axis_index + 1 :])
        step_size = numpy.prod(image.shape[axis + 1 :])

        threadsperblock = (32, 32)
        blockspergrid_x = int(
            math.ceil(image.shape[first_axis_index] / threadsperblock[0])
        )
        blockspergrid_y = int(
            math.ceil(image.shape[second_axis_index] / threadsperblock[1])
        )
        blockspergrid = (blockspergrid_x, blockspergrid_y)

        # In some cases if the image is too small, better have more blocks and less threads per block:
        if blockspergrid_x < 256 or blockspergrid_y < 256:
            threadsperblock = (
                1 if blockspergrid_x < 256 else 32,
                1 if blockspergrid_y < 256 else 32,
            )

            blockspergrid_x = int(
                math.ceil(image.shape[first_axis_index] / threadsperblock[0])
            )
            blockspergrid_y = int(
                math.ceil(image.shape[second_axis_index] / threadsperblock[1])
            )
            blockspergrid = (blockspergrid_x, blockspergrid_y)

        gpu_line_filter_3d[blockspergrid, threadsperblock](
            image.ravel(),
            output.ravel(),
            current_size,
            image.shape[axis],
            length1,
            length2,
            step_size,
            image.shape[first_axis_index],
            image.shape[second_axis_index],
        )

    elif image.ndim == 4:
        axes = list(range(image.ndim))
        axes.remove(axis)
        first_axis_index, second_axis_index, third_axis_index = tuple(axes)
        length1 = numpy.prod(image.shape[first_axis_index + 1 :])
        length2 = numpy.prod(image.shape[second_axis_index + 1 :])
        length3 = numpy.prod(image.shape[third_axis_index + 1 :])
        step_size = numpy.prod(image.shape[axis + 1 :])

        threadsperblock = (8, 8, 8)
        blockspergrid_x = int(
            math.ceil(image.shape[first_axis_index] / threadsperblock[0])
        )
        blockspergrid_y = int(
            math.ceil(image.shape[second_axis_index] / threadsperblock[1])
        )
        blockspergrid_z = int(
            math.ceil(image.shape[third_axis_index] / threadsperblock[2])
        )
        blockspergrid = (blockspergrid_x, blockspergrid_y, blockspergrid_z)

        gpu_line_filter_4d[blockspergrid, threadsperblock](
            image.ravel(),
            output.ravel(),
            current_size,
            image.shape[axis],
            length1,
            length2,
            length3,
            step_size,
            image.shape[first_axis_index],
            image.shape[second_axis_index],
            image.shape[third_axis_index],
        )