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

Code before:
        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 _convert_to_reference(*, reference, arrays):
    """Convert `arrays` to `reference` array's namespace and device."""
    xp_ref, _, device_ref = get_namespace_and_device(reference)
    arrays_converted_list = []
    for array in arrays:
        xp_array, _, device_array = get_namespace_and_device(array)
        if xp_ref == xp_array and device_ref == device_array:
            arrays_converted_list.append(array)
        else:
            try:
                # Note will copy if required
                array_converted = xp_ref.from_dlpack(array, device=device_ref)
            except AttributeError:
                # Convert to numpy
                if _is_numpy_namespace(xp_ref):
                    array_converted = _convert_to_numpy(array, xp_array)
                # Convert from numpy
                elif _is_numpy_namespace(xp_array):
                    array_converted = xp_ref.asarray(array, device=device_ref)
                else:
                    # Convert to numpy then to reference
                    array_np = _convert_to_numpy(array, xp_array)
                    array_converted = xp_ref.asarray(array_np, device=device_ref)
            arrays_converted_list.append(array_converted)

    return tuple(arrays_converted_list)


def _expit(X, xp=None):
    xp, _ = get_namespace(X, xp=xp)
    if _is_numpy_namespace(xp):
        return xp.asarray(special.expit(numpy.asarray(X)))

    return 1.0 / (1.0 + xp.exp(-X))



Review comment (bug):
```suggestion
                # 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
                # should trigger a copy automatically only if needed.
```

Code after:
    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
    ----------
    *arrays : iterable of arrays
        Arrays to (potentially) move.

    xp : namespace
        Array API namespace to move arrays to.

    device : device
        Array API device to move arrays to.

    Returns
    -------
    arrays : tuple or array
        Tuple of arrays with the same namespace and device as reference. Single array
        returned if only one `arrays` input.
    """
    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):
        raise TypeError(
            "Sparse arrays are only accepted (and passed through) when the target "
            "namespace is Numpy"
        )

    converted_arrays = []

    for array, is_sparse, is_none in zip(arrays, sparse_mask, none_mask):
        if is_none:
            converted_arrays.append(None)