Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
test_pocketfft.py590 linesDownload Raw Back to tests
1import queue
2import threading
3
4import pytest
5
6import numpy as np
7from numpy.random import random
8from numpy.testing import IS_WASM, assert_allclose, assert_array_equal, assert_raises
9
10
11def fft1(x):
12    L = len(x)
13    phase = -2j * np.pi * (np.arange(L) / L)
14    phase = np.arange(L).reshape(-1, 1) * phase
15    return np.sum(x * np.exp(phase), axis=1)
16
17
18class TestFFTShift:
19
20    def test_fft_n(self):
21        assert_raises(ValueError, np.fft.fft, [1, 2, 3], 0)
22
23
24class TestFFT1D:
25
26    def test_identity(self):
27        maxlen = 512
28        x = random(maxlen) + 1j * random(maxlen)
29        xr = random(maxlen)
30        for i in range(1, maxlen):
31            assert_allclose(np.fft.ifft(np.fft.fft(x[0:i])), x[0:i],
32                            atol=1e-12)
33            assert_allclose(np.fft.irfft(np.fft.rfft(xr[0:i]), i),
34                            xr[0:i], atol=1e-12)
35
36    @pytest.mark.parametrize("dtype", [np.single, np.double, np.longdouble])
37    def test_identity_long_short(self, dtype):
38        # Test with explicitly given number of points, both for n
39        # smaller and for n larger than the input size.
40        maxlen = 16
41        atol = 5 * np.spacing(np.array(1., dtype=dtype))
42        x = random(maxlen).astype(dtype) + 1j * random(maxlen).astype(dtype)
43        xx = np.concatenate([x, np.zeros_like(x)])
44        xr = random(maxlen).astype(dtype)
45        xxr = np.concatenate([xr, np.zeros_like(xr)])
46        for i in range(1, maxlen * 2):
47            check_c = np.fft.ifft(np.fft.fft(x, n=i), n=i)
48            assert check_c.real.dtype == dtype
49            assert_allclose(check_c, xx[0:i], atol=atol, rtol=0)
50            check_r = np.fft.irfft(np.fft.rfft(xr, n=i), n=i)
51            assert check_r.dtype == dtype
52            assert_allclose(check_r, xxr[0:i], atol=atol, rtol=0)
53
54    @pytest.mark.parametrize("dtype", [np.single, np.double, np.longdouble])
55    def test_identity_long_short_reversed(self, dtype):
56        # Also test explicitly given number of points in reversed order.
57        maxlen = 16
58        atol = 6 * np.spacing(np.array(1., dtype=dtype))
59        x = random(maxlen).astype(dtype) + 1j * random(maxlen).astype(dtype)
60        xx = np.concatenate([x, np.zeros_like(x)])
61        for i in range(1, maxlen * 2):
62            check_via_c = np.fft.fft(np.fft.ifft(x, n=i), n=i)
63            assert check_via_c.dtype == x.dtype
64            assert_allclose(check_via_c, xx[0:i], atol=atol, rtol=0)
65            # For irfft, we can neither recover the imaginary part of
66            # the first element, nor the imaginary part of the last
67            # element if npts is even.  So, set to 0 for the comparison.
68            y = x.copy()
69            n = i // 2 + 1
70            y.imag[0] = 0
71            if i % 2 == 0:
72                y.imag[n - 1:] = 0
73            yy = np.concatenate([y, np.zeros_like(y)])
74            check_via_r = np.fft.rfft(np.fft.irfft(x, n=i), n=i)
75            assert check_via_r.dtype == x.dtype
76            assert_allclose(check_via_r, yy[0:n], atol=atol, rtol=0)
77
78    def test_fft(self):
79        x = random(30) + 1j * random(30)
80        assert_allclose(fft1(x), np.fft.fft(x), atol=1e-6)
81        assert_allclose(fft1(x), np.fft.fft(x, norm="backward"), atol=1e-6)
82        assert_allclose(fft1(x) / np.sqrt(30),
83                        np.fft.fft(x, norm="ortho"), atol=1e-6)
84        assert_allclose(fft1(x) / 30.,
85                        np.fft.fft(x, norm="forward"), atol=1e-6)
86
87    @pytest.mark.parametrize("axis", (0, 1))
88    @pytest.mark.parametrize("dtype", (complex, float))
89    @pytest.mark.parametrize("transpose", (True, False))
90    def test_fft_out_argument(self, dtype, transpose, axis):
91        def zeros_like(x):
92            if transpose:
93                return np.zeros_like(x.T).T
94            else:
95                return np.zeros_like(x)
96
97        # tests below only test the out parameter
98        if dtype is complex:
99            y = random((10, 20)) + 1j * random((10, 20))
100            fft, ifft = np.fft.fft, np.fft.ifft
101        else:
102            y = random((10, 20))
103            fft, ifft = np.fft.rfft, np.fft.irfft
104
105        expected = fft(y, axis=axis)
106        out = zeros_like(expected)
107        result = fft(y, out=out, axis=axis)
108        assert result is out
109        assert_array_equal(result, expected)
110
111        expected2 = ifft(expected, axis=axis)
112        out2 = out if dtype is complex else zeros_like(expected2)
113        result2 = ifft(out, out=out2, axis=axis)
114        assert result2 is out2
115        assert_array_equal(result2, expected2)
116
117    @pytest.mark.parametrize("axis", [0, 1])
118    def test_fft_inplace_out(self, axis):
119        # Test some weirder in-place combinations
120        y = random((20, 20)) + 1j * random((20, 20))
121        # Fully in-place.
122        y1 = y.copy()
123        expected1 = np.fft.fft(y1, axis=axis)
124        result1 = np.fft.fft(y1, axis=axis, out=y1)
125        assert result1 is y1
126        assert_array_equal(result1, expected1)
127        # In-place of part of the array; rest should be unchanged.
128        y2 = y.copy()
129        out2 = y2[:10] if axis == 0 else y2[:, :10]
130        expected2 = np.fft.fft(y2, n=10, axis=axis)
131        result2 = np.fft.fft(y2, n=10, axis=axis, out=out2)
132        assert result2 is out2
133        assert_array_equal(result2, expected2)
134        if axis == 0:
135            assert_array_equal(y2[10:], y[10:])
136        else:
137            assert_array_equal(y2[:, 10:], y[:, 10:])
138        # In-place of another part of the array.
139        y3 = y.copy()
140        y3_sel = y3[5:] if axis == 0 else y3[:, 5:]
141        out3 = y3[5:15] if axis == 0 else y3[:, 5:15]
142        expected3 = np.fft.fft(y3_sel, n=10, axis=axis)
143        result3 = np.fft.fft(y3_sel, n=10, axis=axis, out=out3)
144        assert result3 is out3
145        assert_array_equal(result3, expected3)
146        if axis == 0:
147            assert_array_equal(y3[:5], y[:5])
148            assert_array_equal(y3[15:], y[15:])
149        else:
150            assert_array_equal(y3[:, :5], y[:, :5])
151            assert_array_equal(y3[:, 15:], y[:, 15:])
152        # In-place with n > nin; rest should be unchanged.
153        y4 = y.copy()
154        y4_sel = y4[:10] if axis == 0 else y4[:, :10]
155        out4 = y4[:15] if axis == 0 else y4[:, :15]
156        expected4 = np.fft.fft(y4_sel, n=15, axis=axis)
157        result4 = np.fft.fft(y4_sel, n=15, axis=axis, out=out4)
158        assert result4 is out4
159        assert_array_equal(result4, expected4)
160        if axis == 0:
161            assert_array_equal(y4[15:], y[15:])
162        else:
163            assert_array_equal(y4[:, 15:], y[:, 15:])
164        # Overwrite in a transpose.
165        y5 = y.copy()
166        out5 = y5.T
167        result5 = np.fft.fft(y5, axis=axis, out=out5)
168        assert result5 is out5
169        assert_array_equal(result5, expected1)
170        # Reverse strides.
171        y6 = y.copy()
172        out6 = y6[::-1] if axis == 0 else y6[:, ::-1]
173        result6 = np.fft.fft(y6, axis=axis, out=out6)
174        assert result6 is out6
175        assert_array_equal(result6, expected1)
176
177    def test_fft_bad_out(self):
178        x = np.arange(30.)
179        with pytest.raises(TypeError, match="must be of ArrayType"):
180            np.fft.fft(x, out="")
181        with pytest.raises(ValueError, match="has wrong shape"):
182            np.fft.fft(x, out=np.zeros_like(x).reshape(5, -1))
183        with pytest.raises(TypeError, match="Cannot cast"):
184            np.fft.fft(x, out=np.zeros_like(x, dtype=float))
185
186    @pytest.mark.parametrize('norm', (None, 'backward', 'ortho', 'forward'))
187    def test_ifft(self, norm):
188        x = random(30) + 1j * random(30)
189        assert_allclose(
190            x, np.fft.ifft(np.fft.fft(x, norm=norm), norm=norm),
191            atol=1e-6)
192        # Ensure we get the correct error message
193        with pytest.raises(ValueError,
194                           match='Invalid number of FFT data points'):
195            np.fft.ifft([], norm=norm)
196
197    def test_fft2(self):
198        x = random((30, 20)) + 1j * random((30, 20))
199        assert_allclose(np.fft.fft(np.fft.fft(x, axis=1), axis=0),
200                        np.fft.fft2(x), atol=1e-6)
201        assert_allclose(np.fft.fft2(x),
202                        np.fft.fft2(x, norm="backward"), atol=1e-6)
203        assert_allclose(np.fft.fft2(x) / np.sqrt(30 * 20),
204                        np.fft.fft2(x, norm="ortho"), atol=1e-6)
205        assert_allclose(np.fft.fft2(x) / (30. * 20.),
206                        np.fft.fft2(x, norm="forward"), atol=1e-6)
207
208    def test_ifft2(self):
209        x = random((30, 20)) + 1j * random((30, 20))
210        assert_allclose(np.fft.ifft(np.fft.ifft(x, axis=1), axis=0),
211                        np.fft.ifft2(x), atol=1e-6)
212        assert_allclose(np.fft.ifft2(x),
213                        np.fft.ifft2(x, norm="backward"), atol=1e-6)
214        assert_allclose(np.fft.ifft2(x) * np.sqrt(30 * 20),
215                        np.fft.ifft2(x, norm="ortho"), atol=1e-6)
216        assert_allclose(np.fft.ifft2(x) * (30. * 20.),
217                        np.fft.ifft2(x, norm="forward"), atol=1e-6)
218
219    def test_fftn(self):
220        x = random((30, 20, 10)) + 1j * random((30, 20, 10))
221        assert_allclose(
222            np.fft.fft(np.fft.fft(np.fft.fft(x, axis=2), axis=1), axis=0),
223            np.fft.fftn(x), atol=1e-6)
224        assert_allclose(np.fft.fftn(x),
225                        np.fft.fftn(x, norm="backward"), atol=1e-6)
226        assert_allclose(np.fft.fftn(x) / np.sqrt(30 * 20 * 10),
227                        np.fft.fftn(x, norm="ortho"), atol=1e-6)
228        assert_allclose(np.fft.fftn(x) / (30. * 20. * 10.),
229                        np.fft.fftn(x, norm="forward"), atol=1e-6)
230
231    def test_ifftn(self):
232        x = random((30, 20, 10)) + 1j * random((30, 20, 10))
233        assert_allclose(
234            np.fft.ifft(np.fft.ifft(np.fft.ifft(x, axis=2), axis=1), axis=0),
235            np.fft.ifftn(x), atol=1e-6)
236        assert_allclose(np.fft.ifftn(x),
237                        np.fft.ifftn(x, norm="backward"), atol=1e-6)
238        assert_allclose(np.fft.ifftn(x) * np.sqrt(30 * 20 * 10),
239                        np.fft.ifftn(x, norm="ortho"), atol=1e-6)
240        assert_allclose(np.fft.ifftn(x) * (30. * 20. * 10.),
241                        np.fft.ifftn(x, norm="forward"), atol=1e-6)
242
243    def test_rfft(self):
244        x = random(30)
245        for n in [x.size, 2 * x.size]:
246            for norm in [None, 'backward', 'ortho', 'forward']:
247                assert_allclose(
248                    np.fft.fft(x, n=n, norm=norm)[:(n // 2 + 1)],
249                    np.fft.rfft(x, n=n, norm=norm), atol=1e-6)
250            assert_allclose(
251                np.fft.rfft(x, n=n),
252                np.fft.rfft(x, n=n, norm="backward"), atol=1e-6)
253            assert_allclose(
254                np.fft.rfft(x, n=n) / np.sqrt(n),
255                np.fft.rfft(x, n=n, norm="ortho"), atol=1e-6)
256            assert_allclose(
257                np.fft.rfft(x, n=n) / n,
258                np.fft.rfft(x, n=n, norm="forward"), atol=1e-6)
259
260    def test_rfft_even(self):
261        x = np.arange(8)
262        n = 4
263        y = np.fft.rfft(x, n)
264        assert_allclose(y, np.fft.fft(x[:n])[:n // 2 + 1], rtol=1e-14)
265
266    def test_rfft_odd(self):
267        x = np.array([1, 0, 2, 3, -3])
268        y = np.fft.rfft(x)
269        assert_allclose(y, np.fft.fft(x)[:3], rtol=1e-14)
270
271    def test_irfft(self):
272        x = random(30)
273        assert_allclose(x, np.fft.irfft(np.fft.rfft(x)), atol=1e-6)
274        assert_allclose(x, np.fft.irfft(np.fft.rfft(x, norm="backward"),
275                        norm="backward"), atol=1e-6)
276        assert_allclose(x, np.fft.irfft(np.fft.rfft(x, norm="ortho"),
277                        norm="ortho"), atol=1e-6)
278        assert_allclose(x, np.fft.irfft(np.fft.rfft(x, norm="forward"),
279                        norm="forward"), atol=1e-6)
280
281    def test_rfft2(self):
282        x = random((30, 20))
283        assert_allclose(np.fft.fft2(x)[:, :11], np.fft.rfft2(x), atol=1e-6)
284        assert_allclose(np.fft.rfft2(x),
285                        np.fft.rfft2(x, norm="backward"), atol=1e-6)
286        assert_allclose(np.fft.rfft2(x) / np.sqrt(30 * 20),
287                        np.fft.rfft2(x, norm="ortho"), atol=1e-6)
288        assert_allclose(np.fft.rfft2(x) / (30. * 20.),
289                        np.fft.rfft2(x, norm="forward"), atol=1e-6)
290
291    def test_irfft2(self):
292        x = random((30, 20))
293        assert_allclose(x, np.fft.irfft2(np.fft.rfft2(x)), atol=1e-6)
294        assert_allclose(x, np.fft.irfft2(np.fft.rfft2(x, norm="backward"),
295                        norm="backward"), atol=1e-6)
296        assert_allclose(x, np.fft.irfft2(np.fft.rfft2(x, norm="ortho"),
297                        norm="ortho"), atol=1e-6)
298        assert_allclose(x, np.fft.irfft2(np.fft.rfft2(x, norm="forward"),
299                        norm="forward"), atol=1e-6)
300
301    def test_rfftn(self):
302        x = random((30, 20, 10))
303        assert_allclose(np.fft.fftn(x)[:, :, :6], np.fft.rfftn(x), atol=1e-6)
304        assert_allclose(np.fft.rfftn(x),
305                        np.fft.rfftn(x, norm="backward"), atol=1e-6)
306        assert_allclose(np.fft.rfftn(x) / np.sqrt(30 * 20 * 10),
307                        np.fft.rfftn(x, norm="ortho"), atol=1e-6)
308        assert_allclose(np.fft.rfftn(x) / (30. * 20. * 10.),
309                        np.fft.rfftn(x, norm="forward"), atol=1e-6)
310        # Regression test for gh-27159
311        x = np.ones((2, 3))
312        result = np.fft.rfftn(x, axes=(0, 0, 1), s=(10, 20, 40))
313        assert result.shape == (10, 21)
314        expected = np.fft.fft(np.fft.fft(np.fft.rfft(x, axis=1, n=40),
315                            axis=0, n=20), axis=0, n=10)
316        assert expected.shape == (10, 21)
317        assert_allclose(result, expected, atol=1e-6)
318
319    def test_irfftn(self):
320        x = random((30, 20, 10))
321        assert_allclose(x, np.fft.irfftn(np.fft.rfftn(x)), atol=1e-6)
322        assert_allclose(x, np.fft.irfftn(np.fft.rfftn(x, norm="backward"),
323                        norm="backward"), atol=1e-6)
324        assert_allclose(x, np.fft.irfftn(np.fft.rfftn(x, norm="ortho"),
325                        norm="ortho"), atol=1e-6)
326        assert_allclose(x, np.fft.irfftn(np.fft.rfftn(x, norm="forward"),
327                        norm="forward"), atol=1e-6)
328
329    def test_hfft(self):
330        x = random(14) + 1j * random(14)
331        x_herm = np.concatenate((random(1), x, random(1)))
332        x = np.concatenate((x_herm, x[::-1].conj()))
333        assert_allclose(np.fft.fft(x), np.fft.hfft(x_herm), atol=1e-6)
334        assert_allclose(np.fft.hfft(x_herm),
335                        np.fft.hfft(x_herm, norm="backward"), atol=1e-6)
336        assert_allclose(np.fft.hfft(x_herm) / np.sqrt(30),
337                        np.fft.hfft(x_herm, norm="ortho"), atol=1e-6)
338        assert_allclose(np.fft.hfft(x_herm) / 30.,
339                        np.fft.hfft(x_herm, norm="forward"), atol=1e-6)
340
341    def test_ihfft(self):
342        x = random(14) + 1j * random(14)
343        x_herm = np.concatenate((random(1), x, random(1)))
344        x = np.concatenate((x_herm, x[::-1].conj()))
345        assert_allclose(x_herm, np.fft.ihfft(np.fft.hfft(x_herm)), atol=1e-6)
346        assert_allclose(x_herm, np.fft.ihfft(np.fft.hfft(x_herm,
347                        norm="backward"), norm="backward"), atol=1e-6)
348        assert_allclose(x_herm, np.fft.ihfft(np.fft.hfft(x_herm,
349                        norm="ortho"), norm="ortho"), atol=1e-6)
350        assert_allclose(x_herm, np.fft.ihfft(np.fft.hfft(x_herm,
351                        norm="forward"), norm="forward"), atol=1e-6)
352
353    @pytest.mark.parametrize("op", [np.fft.fftn, np.fft.ifftn,
354                                    np.fft.rfftn, np.fft.irfftn])
355    def test_axes(self, op):
356        x = random((30, 20, 10))
357        axes = [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]
358        for a in axes:
359            op_tr = op(np.transpose(x, a))
360            tr_op = np.transpose(op(x, axes=a), a)
361            assert_allclose(op_tr, tr_op, atol=1e-6)
362
363    @pytest.mark.parametrize("op", [np.fft.fftn, np.fft.ifftn,
364                                    np.fft.fft2, np.fft.ifft2])
365    def test_s_negative_1(self, op):
366        x = np.arange(100).reshape(10, 10)
367        # should use the whole input array along the first axis
368        assert op(x, s=(-1, 5), axes=(0, 1)).shape == (10, 5)
369
370    @pytest.mark.parametrize("op", [np.fft.fftn, np.fft.ifftn,
371                                    np.fft.rfftn, np.fft.irfftn])
372    def test_s_axes_none(self, op):
373        x = np.arange(100).reshape(10, 10)
374        with pytest.warns(match='`axes` should not be `None` if `s`'):
375            op(x, s=(-1, 5))
376
377    @pytest.mark.parametrize("op", [np.fft.fft2, np.fft.ifft2])
378    def test_s_axes_none_2D(self, op):
379        x = np.arange(100).reshape(10, 10)
380        with pytest.warns(match='`axes` should not be `None` if `s`'):
381            op(x, s=(-1, 5), axes=None)
382
383    @pytest.mark.parametrize("op", [np.fft.fftn, np.fft.ifftn,
384                                    np.fft.rfftn, np.fft.irfftn,
385                                    np.fft.fft2, np.fft.ifft2])
386    def test_s_contains_none(self, op):
387        x = random((30, 20, 10))
388        with pytest.warns(match='array containing `None` values to `s`'):
389            op(x, s=(10, None, 10), axes=(0, 1, 2))
390
391    def test_all_1d_norm_preserving(self):
392        # verify that round-trip transforms are norm-preserving
393        x = random(30)
394        x_norm = np.linalg.norm(x)
395        n = x.size * 2
396        func_pairs = [(np.fft.fft, np.fft.ifft),
397                      (np.fft.rfft, np.fft.irfft),
398                      # hfft: order so the first function takes x.size samples
399                      #       (necessary for comparison to x_norm above)
400                      (np.fft.ihfft, np.fft.hfft),
401                      ]
402        for forw, back in func_pairs:
403            for n in [x.size, 2 * x.size]:
404                for norm in [None, 'backward', 'ortho', 'forward']:
405                    tmp = forw(x, n=n, norm=norm)
406                    tmp = back(tmp, n=n, norm=norm)
407                    assert_allclose(x_norm,
408                                    np.linalg.norm(tmp), atol=1e-6)
409
410    @pytest.mark.parametrize("axes", [(0, 1), (0, 2), None])
411    @pytest.mark.parametrize("dtype", (complex, float))
412    @pytest.mark.parametrize("transpose", (True, False))
413    def test_fftn_out_argument(self, dtype, transpose, axes):
414        def zeros_like(x):
415            if transpose:
416                return np.zeros_like(x.T).T
417            else:
418                return np.zeros_like(x)
419
420        # tests below only test the out parameter
421        if dtype is complex:
422            x = random((10, 5, 6)) + 1j * random((10, 5, 6))
423            fft, ifft = np.fft.fftn, np.fft.ifftn
424        else:
425            x = random((10, 5, 6))
426            fft, ifft = np.fft.rfftn, np.fft.irfftn
427
428        expected = fft(x, axes=axes)
429        out = zeros_like(expected)
430        result = fft(x, out=out, axes=axes)
431        assert result is out
432        assert_array_equal(result, expected)
433
434        expected2 = ifft(expected, axes=axes)
435        out2 = out if dtype is complex else zeros_like(expected2)
436        result2 = ifft(out, out=out2, axes=axes)
437        assert result2 is out2
438        assert_array_equal(result2, expected2)
439
440    @pytest.mark.parametrize("fft", [np.fft.fftn, np.fft.ifftn, np.fft.rfftn])
441    def test_fftn_out_and_s_interaction(self, fft):
442        # With s, shape varies, so generally one cannot pass in out.
443        if fft is np.fft.rfftn:
444            x = random((10, 5, 6))
445        else:
446            x = random((10, 5, 6)) + 1j * random((10, 5, 6))
447        with pytest.raises(ValueError, match="has wrong shape"):
448            fft(x, out=np.zeros_like(x), s=(3, 3, 3), axes=(0, 1, 2))
449        # Except on the first axis done (which is the last of axes).
450        s = (10, 5, 5)
451        expected = fft(x, s=s, axes=(0, 1, 2))
452        out = np.zeros_like(expected)
453        result = fft(x, s=s, axes=(0, 1, 2), out=out)
454        assert result is out
455        assert_array_equal(result, expected)
456
457    @pytest.mark.parametrize("s", [(9, 5, 5), (3, 3, 3)])
458    def test_irfftn_out_and_s_interaction(self, s):
459        # Since for irfftn, the output is real and thus cannot be used for
460        # intermediate steps, it should always work.
461        x = random((9, 5, 6, 2)) + 1j * random((9, 5, 6, 2))
462        expected = np.fft.irfftn(x, s=s, axes=(0, 1, 2))
463        out = np.zeros_like(expected)
464        result = np.fft.irfftn(x, s=s, axes=(0, 1, 2), out=out)
465        assert result is out
466        assert_array_equal(result, expected)
467
468
469@pytest.mark.parametrize(
470        "dtype",
471        [np.float32, np.float64, np.complex64, np.complex128])
472@pytest.mark.parametrize("order", ["F", 'non-contiguous'])
473@pytest.mark.parametrize(
474        "fft",
475        [np.fft.fft, np.fft.fft2, np.fft.fftn,
476         np.fft.ifft, np.fft.ifft2, np.fft.ifftn])
477def test_fft_with_order(dtype, order, fft):
478    # Check that FFT/IFFT produces identical results for C, Fortran and
479    # non contiguous arrays
480    rng = np.random.RandomState(42)
481    X = rng.rand(8, 7, 13).astype(dtype, copy=False)
482    # See discussion in pull/14178
483    _tol = 8.0 * np.sqrt(np.log2(X.size)) * np.finfo(X.dtype).eps
484    if order == 'F':
485        Y = np.asfortranarray(X)
486    else:
487        # Make a non contiguous array
488        Y = X[::-1]
489        X = np.ascontiguousarray(X[::-1])
490
491    if fft.__name__.endswith('fft'):
492        for axis in range(3):
493            X_res = fft(X, axis=axis)
494            Y_res = fft(Y, axis=axis)
495            assert_allclose(X_res, Y_res, atol=_tol, rtol=_tol)
496    elif fft.__name__.endswith(('fft2', 'fftn')):
497        axes = [(0, 1), (1, 2), (0, 2)]
498        if fft.__name__.endswith('fftn'):
499            axes.extend([(0,), (1,), (2,), None])
500        for ax in axes:
501            X_res = fft(X, axes=ax)
502            Y_res = fft(Y, axes=ax)
503            assert_allclose(X_res, Y_res, atol=_tol, rtol=_tol)
504    else:
505        raise ValueError
506
507
508@pytest.mark.parametrize("order", ["F", "C"])
509@pytest.mark.parametrize("n", [None, 7, 12])
510def test_fft_output_order(order, n):
511    rng = np.random.RandomState(42)
512    x = rng.rand(10)
513    x = np.asarray(x, dtype=np.complex64, order=order)
514    res = np.fft.fft(x, n=n)
515    assert res.flags.c_contiguous == x.flags.c_contiguous
516    assert res.flags.f_contiguous == x.flags.f_contiguous
517
518@pytest.mark.skipif(IS_WASM, reason="Cannot start thread")
519class TestFFTThreadSafe:
520    threads = 16
521    input_shape = (800, 200)
522
523    def _test_mtsame(self, func, *args):
524        def worker(args, q):
525            q.put(func(*args))
526
527        q = queue.Queue()
528        expected = func(*args)
529
530        # Spin off a bunch of threads to call the same function simultaneously
531        t = [threading.Thread(target=worker, args=(args, q))
532             for i in range(self.threads)]
533        [x.start() for x in t]
534
535        [x.join() for x in t]
536        # Make sure all threads returned the correct value
537        for i in range(self.threads):
538            assert_array_equal(q.get(timeout=5), expected,
539                'Function returned wrong value in multithreaded context')
540
541    def test_fft(self):
542        a = np.ones(self.input_shape) * 1 + 0j
543        self._test_mtsame(np.fft.fft, a)
544
545    def test_ifft(self):
546        a = np.ones(self.input_shape) * 1 + 0j
547        self._test_mtsame(np.fft.ifft, a)
548
549    def test_rfft(self):
550        a = np.ones(self.input_shape)
551        self._test_mtsame(np.fft.rfft, a)
552
553    def test_irfft(self):
554        a = np.ones(self.input_shape) * 1 + 0j
555        self._test_mtsame(np.fft.irfft, a)
556
557
558def test_irfft_with_n_1_regression():
559    # Regression test for gh-25661
560    x = np.arange(10)
561    np.fft.irfft(x, n=1)
562    np.fft.hfft(x, n=1)
563    np.fft.irfft(np.array([0], complex), n=10)
564
565
566def test_irfft_with_n_large_regression():
567    # Regression test for gh-25679
568    x = np.arange(5) * (1 + 1j)
569    result = np.fft.hfft(x, n=10)
570    expected = np.array([20., 9.91628173, -11.8819096, 7.1048486,
571                         -6.62459848, 4., -3.37540152, -0.16057669,
572                         1.8819096, -20.86055364])
573    assert_allclose(result, expected)
574
575
576@pytest.mark.parametrize("fft", [
577    np.fft.fft, np.fft.ifft, np.fft.rfft, np.fft.irfft
578])
579@pytest.mark.parametrize("data", [
580    np.array([False, True, False]),
581    np.arange(10, dtype=np.uint8),
582    np.arange(5, dtype=np.int16),
583])
584def test_fft_with_integer_or_bool_input(data, fft):
585    # Regression test for gh-25819
586    result = fft(data)
587    float_data = data.astype(np.result_type(data, 1.))
588    expected = fft(float_data)
589    assert_array_equal(result, expected)
590 
codekingpro/portable-devtools · Team Ai