Repository: ivy-llc/ivy

Issue:
ifftshift
**Part of:** #1532
**Frontend:** Numpy
**Function:** `numpy.fft.ifftshift`


Discussion:

Resolving patch:
diff --git a/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py b/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py
--- a/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py
+++ b/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py
@@ -1,5 +1,6 @@
 import ivy
 from ivy.functional.frontends.numpy.func_wrapper import to_ivy_arrays_and_back
+from ivy.func_wrapper import with_unsupported_dtypes
 
 
 @to_ivy_arrays_and_back
@@ -8,3 +9,54 @@ def ifft(a, n=None, axis=-1, norm=None):
     if norm is None:
         norm = "backward"
     return ivy.ifft(a, axis, norm=norm, n=n)
+
+
+@to_ivy_arrays_and_back
+@with_unsupported_dtypes({"1.23.0 and below": ("float16",)}, "numpy")
+def ifftshift(x, axes=None):
+    """
+    The inverse of `fftshift`. Although identical for even-length `x`, the
+    functions differ by one sample for odd-length `x`.
+    Parameters
+    ----------
+    x : array_like
+        Input array.
+    axes : int or shape tuple, optional
+        Axes over which to calculate.  Defaults to None, which shifts all axes.
+    Returns
+    -------
+    y : ndarray
+        The shifted array.
+    See Also
+    --------
+    fftshift : Shift zero-frequency component to the center of the spectrum.
+    Examples
+    --------
+    >>> arr = ivy.functional.frontends.numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
+    >>> arr
+    array([[ 1,  2,  3],
+           [ 4,  5,  6],
+           [ 7,  8,  9]])
+    >>> ivy.functional.frontends.numpy.fft.ifftshift(arr, axes=(0, 1))
+    array([[ 5,  6,  4],
+           [ 9,  7,  8],
+           [ 3,  1,  2]])
+    """
+
+    x = ivy.asarray(x)
+
+    if axes is None:
+        axes = tuple(range(x.ndim))
+        shift = [-(dim // 2) for dim in x.shape]
+    elif isinstance(axes, (int,
+                           type(ivy.uint8),
+                           type(ivy.uint16),
+                           type(ivy.uint32),
+                           type(ivy.uint64))):
+        shift = -(x.shape[axes] // 2)
+    else:
+        shift = [-(x.shape[ax] // 2) for ax in axes]
+
+    roll = ivy.roll(x, shift, axis=axes)
+
+    return roll


Test patch:
diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_fft/test_discrete_fourier_transform.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_fft/test_discrete_fourier_transform.py
--- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_fft/test_discrete_fourier_transform.py
+++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_fft/test_discrete_fourier_transform.py
@@ -22,3 +22,23 @@ def test_numpy_iftt(dtype_and_x, frontend, test_flags, fn_tree, on_device):
         axis=-1,
         norm=None,
     )
+
+
+@handle_frontend_test(
+    fn_tree="numpy.fft.ifftshift",
+    dtype_and_x=helpers.dtype_and_values(
+        available_dtypes=helpers.get_dtypes("float"), shape=(4,), array_api_dtypes=True
+    ),
+)
+def test_numpy_ifttshift(dtype_and_x, frontend, test_flags, fn_tree, on_device):
+    input_dtype, arr = dtype_and_x
+    helpers.test_frontend_function(
+        input_dtypes=input_dtype,
+        frontend=frontend,
+        test_flags=test_flags,
+        fn_tree=fn_tree,
+        on_device=on_device,
+        test_values=True,
+        x=arr[0],
+        axes=None,
+    )