mirror of
https://github.com/ml-explore/mlx.git
synced 2025-10-18 15:28:16 +08:00
add fftshift and ifftshift fft helpers (#2135)
* add fftshift and ifftshift fft helpers * address comments * axes have to be iterable * fix fp error in roll + add test --------- Co-authored-by: Aashiq Dheeraj <aashiq@aashiq-mbp-m4.local>
This commit is contained in:
@@ -199,6 +199,68 @@ class TestFFT(mlx_tests.MLXTestCase):
|
||||
with self.assertRaises(ValueError):
|
||||
mx.fft.irfftn(x)
|
||||
|
||||
def test_fftshift(self):
|
||||
# Test 1D arrays
|
||||
r = np.random.rand(100).astype(np.float32)
|
||||
self.check_mx_np(mx.fft.fftshift, np.fft.fftshift, r)
|
||||
|
||||
# Test with specific axis
|
||||
r = np.random.rand(4, 6).astype(np.float32)
|
||||
self.check_mx_np(mx.fft.fftshift, np.fft.fftshift, r, axes=[0])
|
||||
self.check_mx_np(mx.fft.fftshift, np.fft.fftshift, r, axes=[1])
|
||||
self.check_mx_np(mx.fft.fftshift, np.fft.fftshift, r, axes=[0, 1])
|
||||
|
||||
# Test with negative axes
|
||||
self.check_mx_np(mx.fft.fftshift, np.fft.fftshift, r, axes=[-1])
|
||||
|
||||
# Test with odd lengths
|
||||
r = np.random.rand(5, 7).astype(np.float32)
|
||||
self.check_mx_np(mx.fft.fftshift, np.fft.fftshift, r)
|
||||
self.check_mx_np(mx.fft.fftshift, np.fft.fftshift, r, axes=[0])
|
||||
|
||||
# Test with complex input
|
||||
r = np.random.rand(8, 8).astype(np.float32)
|
||||
i = np.random.rand(8, 8).astype(np.float32)
|
||||
c = r + 1j * i
|
||||
self.check_mx_np(mx.fft.fftshift, np.fft.fftshift, c)
|
||||
|
||||
def test_ifftshift(self):
|
||||
# Test 1D arrays
|
||||
r = np.random.rand(100).astype(np.float32)
|
||||
self.check_mx_np(mx.fft.ifftshift, np.fft.ifftshift, r)
|
||||
|
||||
# Test with specific axis
|
||||
r = np.random.rand(4, 6).astype(np.float32)
|
||||
self.check_mx_np(mx.fft.ifftshift, np.fft.ifftshift, r, axes=[0])
|
||||
self.check_mx_np(mx.fft.ifftshift, np.fft.ifftshift, r, axes=[1])
|
||||
self.check_mx_np(mx.fft.ifftshift, np.fft.ifftshift, r, axes=[0, 1])
|
||||
|
||||
# Test with negative axes
|
||||
self.check_mx_np(mx.fft.ifftshift, np.fft.ifftshift, r, axes=[-1])
|
||||
|
||||
# Test with odd lengths
|
||||
r = np.random.rand(5, 7).astype(np.float32)
|
||||
self.check_mx_np(mx.fft.ifftshift, np.fft.ifftshift, r)
|
||||
self.check_mx_np(mx.fft.ifftshift, np.fft.ifftshift, r, axes=[0])
|
||||
|
||||
# Test with complex input
|
||||
r = np.random.rand(8, 8).astype(np.float32)
|
||||
i = np.random.rand(8, 8).astype(np.float32)
|
||||
c = r + 1j * i
|
||||
self.check_mx_np(mx.fft.ifftshift, np.fft.ifftshift, c)
|
||||
|
||||
def test_fftshift_errors(self):
|
||||
# Test invalid axes
|
||||
x = mx.array(np.random.rand(4, 4).astype(np.float32))
|
||||
with self.assertRaises(ValueError):
|
||||
mx.fft.fftshift(x, axes=[2])
|
||||
with self.assertRaises(ValueError):
|
||||
mx.fft.fftshift(x, axes=[-3])
|
||||
|
||||
# Test empty array
|
||||
x = mx.array([])
|
||||
self.assertTrue(mx.array_equal(mx.fft.fftshift(x), x))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
@@ -2961,6 +2961,11 @@ class TestOps(mlx_tests.MLXTestCase):
|
||||
y2 = mx.roll(x, s, a)
|
||||
self.assertTrue(mx.array_equal(y1, y2).item())
|
||||
|
||||
def test_roll_errors(self):
|
||||
x = mx.array([])
|
||||
result = mx.roll(x, [0], [0])
|
||||
self.assertTrue(mx.array_equal(result, x))
|
||||
|
||||
def test_real_imag(self):
|
||||
x = mx.random.uniform(shape=(4, 4))
|
||||
out = mx.real(x)
|
||||
|
Reference in New Issue
Block a user