Repository: scipy/scipy
File: scipy/sparse/linalg/tests/test_interface.py (Python)

Code before:
        return v

    # It should call matvec exactly once (in order to determine the
    # operator dtype)
    interface.LinearOperator((2, 2), matvec=matvec, xp=xp)
    assert_equal(call_count[0], 1)


INT_DTYPES = (np.int8, np.int16, np.int32, np.int64)
REAL_DTYPES = (np.float32, np.float64, np.longdouble)
COMPLEX_DTYPES = (np.complex64, np.complex128, np.clongdouble)
INEXACTDTYPES = REAL_DTYPES + COMPLEX_DTYPES
ALLDTYPES = INT_DTYPES + INEXACTDTYPES


@pytest.mark.parametrize("test_dtype", ALLDTYPES)
def test_determine_lo_dtype_from_matvec(test_dtype, xp):
    if "longdouble" in test_dtype.__name__ and not is_numpy(xp):
        pytest.skip("longdoubles are only tested for `np`")
    # gh-19209
    scalar = xp.asarray(np.array(1, dtype=test_dtype))
    def mv(v):
        return xp.stack([scalar * v[0], v[1]])

    lo = interface.LinearOperator((2, 2), matvec=mv, xp=xp)
    # expected dtype depends on if mixed exact-inexact promotion is defined
    # since dtype determination follows the following procedure:
    # - take the dtype from calling `matvec` on an `int8`
    # - unless that fails (e.g. via overflow or no mixed exact-inexact promotion),
    #   in which case use the default integral dtype
    expected = scalar.dtype
    if test_dtype in globals()["INEXACTDTYPES"]:
        try:
            xp.asarray(2) + xp.asarray(2.0)
        except TypeError:
            expected = xpx.default_dtype(xp, kind="integral")
    assert lo.dtype == expected


def test_determine_lo_dtype_for_int(xp):
    # gh-19209
    # test Python int larger than int8 max cast to some int
    def mv(v):
        return xp.asarray([128 * v[0], v[1]])

    lo = interface.LinearOperator((2, 2), matvec=mv, xp=xp)
    assert xp.isdtype(lo.dtype, "integral")


def test_adjoint_conjugate(xp):
    X = xp.asarray([[1j]], dtype=xp.complex128)

Review comment (bug):
this was just wrong, the `try`-`except` below was hiding the failure with array-api-strict

Code after:

    def matvec(v):
        call_count[0] += 1
        return v

    # It should call matvec exactly once (in order to determine the
    # operator dtype)
    interface.LinearOperator((2, 2), matvec=matvec, xp=xp)
    assert_equal(call_count[0], 1)


INT_DTYPES = (np.int8, np.int16, np.int32, np.int64)
REAL_DTYPES = (np.float32, np.float64, np.longdouble)
COMPLEX_DTYPES = (np.complex64, np.complex128, np.clongdouble)
INEXACTDTYPES = REAL_DTYPES + COMPLEX_DTYPES
ALLDTYPES = INT_DTYPES + INEXACTDTYPES


@pytest.mark.parametrize("test_dtype", ALLDTYPES)
def test_determine_lo_dtype_from_matvec(test_dtype, xp):
    if "longdouble" in test_dtype.__name__ and not is_numpy(xp):
        pytest.skip("longdoubles are only tested for `np`")
    # gh-19209
    scalar = xp.asarray(np.array(1, dtype=test_dtype))
    def mv(v):
        return xp.stack([scalar * v[0], v[1]])

    lo = interface.LinearOperator((2, 2), matvec=mv, xp=xp)
    # expected dtype depends on if mixed exact-inexact promotion is defined
    # since dtype determination follows the following procedure:
    # - take the dtype from calling `matvec` on an `int8`
    # - unless that fails (e.g. via overflow or no mixed exact-inexact promotion),
    #   in which case use the default integral dtype
    expected = scalar.dtype
    if xp.isdtype(expected, ("real floating", "complex floating")):
        try:
            xp.asarray(2) + xp.asarray(2.0)
        except TypeError:
            expected = xpx.default_dtype(xp, kind="integral")
    assert lo.dtype == expected


def test_determine_lo_dtype_for_int(xp):
    # gh-19209
    # test Python int larger than int8 max cast to some int
    def mv(v):
        return xp.asarray([128 * v[0], v[1]])

    lo = interface.LinearOperator((2, 2), matvec=mv, xp=xp)
    assert xp.isdtype(lo.dtype, "integral")