Repository: scipy/scipy
File: scipy/signal/tests/test_ltisys.py (Python)

Code before:
        assert D.shape == (C_.shape[0], B_.shape[1])

    def test_missing_BC(self, xp):
        A_, D_ = map(xp.asarray, (self.A, self.D))
        A, B, C, D = abcd_normalize(A=A_, D=D_)
        assert B.shape[0] == A.shape[0]
        assert B.shape[1] == D.shape[1]
        assert C.shape[0] == D.shape[0]
        assert C.shape[1] == A.shape[0]
        assert B.shape == (A_.shape[0], D_.shape[1])
        assert C.shape == (D_.shape[0], A_.shape[0])

    def test_missing_ABC_fails(self, xp):
        assert_raises(ValueError, abcd_normalize, D=xp.asarray(self.D))

    def test_missing_BD_fails(self, xp):
        A, C = xp.asarray(self.A),xp.asarray(self.C)
        assert_raises(ValueError, abcd_normalize, A=A, C=C)

    def test_missing_CD_fails(self, xp):
        A, B = xp.asarray(self.A), xp.asarray(self.B)
        assert_raises(ValueError, abcd_normalize, A=A, B=B)

    @pytest.mark.parametrize(
        "A_dtype,B_dtype,C_dtype,D_dtype,expected_dtype",
        [
            ("int64", "int64", "int64", "int64", "float64"),
            ("float32", "float32", "float32", "float32", "float32"),
            ("float32", "float32", "float32", "float64", "float64"),
            ("complex64", "complex64", "complex64", "complex64", "complex64"),
            ("complex128", "complex128", "complex128", "complex128", "complex128"),
            ("float64", "float64", "complex128", "float64", "complex128"),
            (None, "int64", "int64", "int64", "float64"),
            (None, "float32", "float32", "float32", "float32"),
            (None, "float32", "float32", "float64", "float64"),
            (None, "complex64", "complex64", "complex64", "complex64"),
            (None, "complex128", "complex128", "complex128", "complex128"),
            (None, "float64", "complex128", "float64", "complex128"),
        ]
    )
    # Also check case where one input array has size zero.
    @pytest.mark.parametrize("D", [[[2.5]], [[]]])
    def test_dtypes(
            self, D, A_dtype, B_dtype, C_dtype, D_dtype, expected_dtype, xp
    ):
        # This skip should not be needed for long.
        if DEFAULT_F32 and is_torch(xp) and B_dtype == "int64":
            pytest.xfail(
                reason=(
                    "xp_promote casts ints to default dtype"
                    " when using force_floating=True with torch."

Review comment (bug):
Why not simplify this, resolve the `xfail`, and (slightly) strengthen the test by:
- `parametrize`ing over input types separately (unless this test is slow),
- determining the expected type (or error behavior) with `xp_result_type`?

After all, the point of the dtype test should be to look out for accidental promotion *other than* a call to `xp_promote`, not to test `xp_promote`/`xp_result_type`. If deemed necessary, you can add checks of the behavior of `xp_promote`/`xp_result_type` separately.

Code after:
        A, B, C, D = abcd_normalize(A=A_, D=D_)
        assert B.shape[0] == A.shape[0]
        assert B.shape[1] == D.shape[1]
        assert C.shape[0] == D.shape[0]
        assert C.shape[1] == A.shape[0]
        assert B.shape == (A_.shape[0], D_.shape[1])
        assert C.shape == (D_.shape[0], A_.shape[0])

    def test_missing_ABC_fails(self, xp):
        assert_raises(ValueError, abcd_normalize, D=xp.asarray(self.D))

    def test_missing_BD_fails(self, xp):
        A, C = xp.asarray(self.A),xp.asarray(self.C)
        assert_raises(ValueError, abcd_normalize, A=A, C=C)

    def test_missing_CD_fails(self, xp):
        A, B = xp.asarray(self.A), xp.asarray(self.B)
        assert_raises(ValueError, abcd_normalize, A=A, B=B)


    @pytest.mark.parametrize(
        "A_dtype",
        # A_dtype=None here means to pass None as the value for A
        [None, "int64", "float32", "float64", "complex64", "complex128"],
    )
    @pytest.mark.parametrize(
        "B_dtype",
        [None, "int64", "float32", "float64", "complex64", "complex128"],
    )
    @pytest.mark.parametrize(
        "C_dtype",
        ["int64", "float32", "float64", "complex64", "complex128"],
    )
    @pytest.mark.parametrize(
        "D_dtype",
        ["int64", "float32", "float64", "complex64", "complex128"],
    )
    # Also check case where one input array has size zero.
    @pytest.mark.parametrize("D", [[[2.5]], [[]]])
    def test_dtypes(self, D, A_dtype, B_dtype, C_dtype, D_dtype, xp):
       
        args = []
        for X, X_dtype in zip(
                [self.A, self.B, self.C, D],
                [A_dtype, B_dtype, C_dtype, D_dtype]
        ):
            args.append(
                xp.asarray(X, dtype=getattr(xp, X_dtype))
                if X_dtype is not None else None
            )
        A, B, C, D = args