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

Code before:
        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))


def _validate_diagonal_args(array, value, xp):
    """Validate arguments to `_fill_diagonal`/`_add_to_diagonal`."""
    if array.ndim != 2:
        raise ValueError(
            f"`array` should be 2D. Got array with shape {tuple(array.shape)}"
        )

    value = xp.asarray(value, dtype=array.dtype, device=device(array))
    if value.ndim not in [0, 1]:
        raise ValueError(

Review comment (suggestion):
```suggestion
                    # There is no generic way to convert from namespace A to B
                    # So we first convert from A to numpy and then from numpy to B
                    # The way to avoid this round trip is to lobby for DLpack support
                    # in libraries A and B
```

Code after:
    """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)
        elif is_sparse:
            converted_arrays.append(array)
        else:
            xp_array, _, device_array = get_namespace_and_device(array)
            if xp == xp_array and device == 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