Repository: scikit-learn/scikit-learn
File: sklearn/utils/_array_api.py (Python)

Code before:
    )
    arrays_device = device(*array_list, **skip_remove_kwargs)

    if xp is None:
        xp, is_array_api = get_namespace(*array_list, **skip_remove_kwargs)
    else:
        xp, is_array_api = xp, True

    if is_array_api:
        return xp, is_array_api, arrays_device
    else:
        return xp, False, arrays_device


def move_to(*arrays, xp_ref, device_ref):
    """Convert `arrays` to `namespace` and `device`.

    * If `xp_ref` is not numpy, `arrays` cannot contain sparse arrays.
    * If `xp_ref` is numpy, sparse arrays are returned unaltered.
    * If any `arrays` is None, None will be returned.
    """
    sparse_mask = [sp.issparse(array) for array in arrays]
    none_mask = [array is None for array in arrays]
    if any(sparse_mask) and not _is_numpy_namespace(xp_ref):
        raise TypeError(
            "Array inputs cannot contain both sparse arrays and non-NumPy arrays."
        )
    # Early return if all `arrays` are sparse or None (to numpy)
    if all(
        sparse_mask[i] or none_mask[i] for i in range(len(arrays))
    ) and _is_numpy_namespace(xp_ref):
        return arrays

    converted_arrays = []

    for i, array in enumerate(arrays):
        if none_mask[i]:
            converted_arrays.append(None)
        elif sparse_mask[i]:
            converted_arrays.append(array)
        else:
            xp_array, _, device_array = get_namespace_and_device(array)
            if xp_ref == xp_array and device_ref == device_array:
                converted_arrays.append(array)
            else:
                try:
                    # The dlpack protocol is the future proof and library agnostic
                    # method to transfer arrays across namespace and device boundaries
                    # hence this method is attempted first and going through NumPy is
                    # only used as fallback in case of failure.
                    # Note: copy=None is the default since 2023.12. Namespace libraries

Review comment (suggestion):
```suggestion
            "Sparse arrays are only supported if the namespace is numpy."
```

Code after:
        Types to ignore in the arrays.
    xp : module, default=None
        Precomputed array namespace module. When passed, typically from a caller
        that has already performed inspection of its own inputs, skips array
        namespace inspection.

    Returns
    -------
    namespace : module
        Namespace shared by array objects. If any of the `arrays` are not arrays,
        the namespace defaults to NumPy.
    is_array_api_compliant : bool
        True if the arrays are containers that implement the Array API spec.
        Always False when array_api_dispatch=False.
    device : device
        `device` object (see the "Device Support" section of the array API spec).
    """
    skip_remove_kwargs = dict(remove_none=False, remove_types=[])

    array_list = _remove_non_arrays(
        *array_list,
        remove_none=remove_none,
        remove_types=remove_types,
    )
    arrays_device = device(*array_list, **skip_remove_kwargs)

    if xp is None:
        xp, is_array_api = get_namespace(*array_list, **skip_remove_kwargs)
    else:
        xp, is_array_api = xp, True

    if is_array_api:
        return xp, is_array_api, arrays_device
    else:
        return xp, False, arrays_device


def move_to(*arrays, xp, device):
    """Move all arrays to `xp` and `device`.

    Each array will be moved to the reference namespace and device if
    it is not already using it. Otherwise the array is left unchanged.

    `array` may contain `None` entries, these are left unchanged.

    Sparse arrays are accepted (as pass through) if the reference namespace is
    Numpy, in which case they are returned unchanged. Otherwise a `TypeError`
    is raised.

    Parameters
    ----------