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

Code before:
    # Verify IIR filter coefficients with the paper's MATLAB implementation
    def test_iir_ba_output(self, xp):
        b, a = gammatone(440, 'iir', fs=16000, xp=xp)
        b2 = [1.31494461367464e-06, -5.03391196645395e-06,
              7.00649426000897e-06, -4.18951968419854e-06,
              9.02614910412011e-07]
        a2 = [1.0, -7.65646235454218,
              25.7584699322366, -49.7319214483238,
              60.2667361289181, -46.9399590980486,
              22.9474798808461, -6.43799381299034,
              0.793651554625368]
        b2, a2 = map(xp.asarray, (b2, a2))
        xp_assert_close(b, b2, atol=1e-10, rtol=5e-5)
        xp_assert_close(a, a2, atol=1e-10, rtol=5e-5)

    def test_fs_validation(self):
        with pytest.raises(ValueError, match="Sampling.*single scalar"):
            gammatone(440, 'iir', fs=np.asarray([10, 20]))


@make_xp_test_case(findfreqs)
class TestFindFreqs:
    @pytest.mark.parametrize("kind", ["ba", "zp"])
    def test_findfreqs_log_spacing(self, xp, kind):
        N = 30
        w = findfreqs(xp.asarray([1.2]), xp.asarray([3.6, 9.8]), N=N, kind=kind)
        ratio = xp.diff(xp.log10(w))
        xp_assert_close(ratio, ratio[0]*xp.ones(N - 1, dtype=xp_default_dtype(xp)))

    def test_findfreqs_ba_zp_equiv(self, xp):
        num, den = [1.4, 2], [1, 3.8, 2]
        zeros, poles = np.roots(num), np.roots(den)

        ba = findfreqs(xp.asarray(num), xp.asarray(den), N=30, kind="ba")
        zp = findfreqs(xp.asarray(zeros), xp.asarray(poles), N=30, kind="zp")

        xp_assert_close(ba, zp)


Review comment (bug):
Copied from my massive docs PR, https://github.com/scipy/scipy/pull/24130/files#diff-87d234831f50304546986134d3e6e8743a6c5032eb7527ff9cf0de6f6b4af5fdR764-R773

```
The intention behind testing with different default dtypes is primarily to catch
subtle bugs that can arise with the ``torch`` backend due to internal array creation
that does not explicitly specify a dtype. The intention is not to implicitly test
that functions are numerically accurate with both ``float32`` and ``float64`` inputs,
or that input dtype controls output dtype. These tasks should instead be accomplished
mindfully by explicitly setting dtypes within tests. For the sake of consistency,
tests intended to be run with the ``torch`` backend should not use array creation
functions without explicitly setting the dtype. At the time of writing, there are many
tests in the test suite which do not follow this practice, and this could be a good source
of first issues for new contributors.
```

You can fix the remaining CI failure by explicitly adding `dtype=xp.float64` in all array creation functions here.


Code after:
    # Verify IIR filter coefficients with the paper's MATLAB implementation
    def test_iir_ba_output(self, xp):
        b, a = gammatone(440, 'iir', fs=16000, xp=xp)
        b2 = [1.31494461367464e-06, -5.03391196645395e-06,
              7.00649426000897e-06, -4.18951968419854e-06,
              9.02614910412011e-07]
        a2 = [1.0, -7.65646235454218,
              25.7584699322366, -49.7319214483238,
              60.2667361289181, -46.9399590980486,
              22.9474798808461, -6.43799381299034,
              0.793651554625368]
        b2, a2 = map(xp.asarray, (b2, a2))
        xp_assert_close(b, b2, atol=1e-10, rtol=5e-5)
        xp_assert_close(a, a2, atol=1e-10, rtol=5e-5)

    def test_fs_validation(self):
        with pytest.raises(ValueError, match="Sampling.*single scalar"):
            gammatone(440, 'iir', fs=np.asarray([10, 20]))


@make_xp_test_case(findfreqs)
class TestFindFreqs:
    @pytest.mark.parametrize("kind", ["ba", "zp"])
    def test_findfreqs_log_spacing(self, xp, kind):
        N = 30
        w = findfreqs(xp.asarray([1.2], dtype=xp.float64),
                      xp.asarray([3.6, 9.8], dtype=xp.float64), N=N, kind=kind)
        ratio = xp.diff(xp.log10(w))
        xp_assert_close(ratio, ratio[0]*xp.ones(N - 1, dtype=xp.float64))

    def test_findfreqs_ba_zp_equiv(self, xp):
        num, den = [1.4, 2], [1, 3.8, 2]
        zeros = xp.asarray(np.roots(num))
        poles = xp.asarray(np.roots(den))

        ba = findfreqs(xp.asarray(num, dtype=xp.float64),
                       xp.asarray(den, dtype=xp.float64), N=30, kind="ba")
        zp = findfreqs(zeros, poles, N=30, kind="zp")

        xp_assert_close(ba, zp)