From 4b2a31781c8eb9d262bdd392adc67a73e97c7b2c Mon Sep 17 00:00:00 2001 From: IsaiJimenezTalonia Date: Wed, 13 Sep 2023 14:56:07 -0600 Subject: [PATCH] Added ifft2 below Add Discrete Fourier Transform functions to Numpy Frontend #1532 --- .idea/ivy.iml | 2 +- .idea/misc.xml | 7 +- .../_template__of_py_test.xml | 3 +- .idea/vcs.xml | 3 + .../numpy/fft/discrete_fourier_transform.py | 8 ++ ivy/functional/ivy/experimental/layers.py | 86 +++++++++++++++++++ .../test_discrete_fourier_transform.py | 24 ++++++ .../test_experimental/test_nn/test_layers.py | 64 ++++++++++++++ 8 files changed, 193 insertions(+), 4 deletions(-) diff --git a/.idea/ivy.iml b/.idea/ivy.iml index 4e727c649cb5b..476ff533250e1 100644 --- a/.idea/ivy.iml +++ b/.idea/ivy.iml @@ -2,7 +2,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index 4d1d4d4ea1dd0..451115a236d7c 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,9 +1,14 @@ + + - + diff --git a/.idea/runConfigurations/_template__of_py_test.xml b/.idea/runConfigurations/_template__of_py_test.xml index ad485cdf211d9..77c2d04aa9f4a 100644 --- a/.idea/runConfigurations/_template__of_py_test.xml +++ b/.idea/runConfigurations/_template__of_py_test.xml @@ -8,7 +8,6 @@ + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7f4cb41..9ebffe28967e8 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,8 @@ + + + \ No newline at end of file diff --git a/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py b/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py index 9d0b890841772..7f1772c71ca2e 100644 --- a/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py +++ b/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py @@ -103,6 +103,14 @@ def ifftshift(x, axes=None): return roll +@with_unsupported_dtypes({"1.25.2 and below": ("float16",)}, "numpy") +@to_ivy_arrays_and_back +def iffttwo(a, shapeLength=None, axesNumber=2, norm=None): + a = ivy.asarray(a, dtype=ivy.complex128) + a = ivy.iffttwo(a, s=shapeLength, axes=axesNumber, norm=norm) + return a + + @with_unsupported_dtypes({"1.25.2 and below": ("float16",)}, "numpy") @to_ivy_arrays_and_back def ihfft(a, n=None, axis=-1, norm=None): diff --git a/ivy/functional/ivy/experimental/layers.py b/ivy/functional/ivy/experimental/layers.py index 8b8db56bd375c..56bb8b3131b58 100644 --- a/ivy/functional/ivy/experimental/layers.py +++ b/ivy/functional/ivy/experimental/layers.py @@ -2636,6 +2636,92 @@ def fft2( } +@handle_backend_invalid +@handle_nestable +@handle_array_like_without_promotion +@handle_out_argument +@handle_exceptions +@to_native_arrays_and_back +def iffttwo( + inputArray: Union[ivy.Array, ivy.NativeArray], + shapeLength: Optional[Union[int, Tuple[int, ...]]] = None, + axesNumber: Optional[Union[int, Tuple[int, ...]]] = None, + *, + normalization: str = "backward", + out: Optional[ivy.Array] = None, +) -> ivy.Array: + r""" + Compute the 2-dimensional inverse discrete Fourier Transform. + + Parameters + ---------- + inputArray: + Input array of complex numbers. + shapeLength: + Shape (length of transformed axis) of the output (`s[0]` refers to axis 0, + `s[1]` to axis 1, etc.). If given shape is smaller than that of the input, + the input is cropped. If larger, input is padded with zeros. If `s` is not + given, shape of input along axes specified by axes is used. + axesNumber: + Axes over which to compute the IFFT. If not given, last `len(s)` axes are + used, or all axes if `s` is also not specified. Repeated indices in axes + means inverse transform over that axis is performed multiple times. + normalization: + Indicates direction of the forward/backward pair of transforms is scaled + and with what normalization factor. "backward" indicates no normalization. + "ortho" indicates normalization by $\frac{1}{\sqrt{n}}$. "forward" + indicates normalization by $\frac{1}{n}$. + out + Optional output array for writing the result to. It must have a shape that + the inputs broadcast to. + + Returns + ------- + out + The truncated or zero-padded input, transformed along the axes indicated + by axes, or by a combination of s or x, as explained in the parameters + section above. + + Raises + ------ + ValueError + If `s` and `axes` have different length. + IndexError + If an element of axes is larger than the number of axes of x. + + Examples + -------- + >>> inputArray = ivy.array([[0.24730653+0.90832391j, 0.49495562+0.9039565j, + ... 0.98193269+0.49560517j], + ... [0.93280757+0.48075343j, 0.28526384+0.3351205j, + ... 0.2343787 +0.83528011j]]) + >>> y = ivy.iffttwo(inputArray) + >>> print(y) + ivy.array([[ 0.51476765+0.66160417j, -0.04319742-0.05411636j, + -0.015561 -0.04216015j], + [ 0.06310689+0.05347854j, -0.13392983+0.16052352j, + -0.08371392+0.17252843j], + [-0.0031429 +0.05421245j, -0.10446617-0.17747098j, + 0.05344324+0.07972424j]]) + + >>> inputArray = ivy.array([[0.24730653+0.90832391j, 0.49495562+0.9039565j, + ... 0.98193269+0.49560517j], + ... [0.93280757+0.48075343j, 0.28526384+0.3351205j, + ... 0.2343787 +0.83528011j]]) + >>>b=ivy.iffttwo(inputArray,shapeLength=[2,1],axesNumber=[0,1],normalization='ortho') + >>> print(b) + ivy.array([[ 0.8344667 +0.98222595j], + [-0.48472244+0.30233797j]]) + """ + return ivy.current_backend(inputArray).iffttwo( + inputArray, + shapeLength=shapeLength, + axesNumber=axesNumber, + normalization=normalization, + out=out, + ) + + @handle_exceptions @handle_backend_invalid @handle_nestable 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 index 9e121cc13268c..495a22bd2d0af 100644 --- 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 @@ -7,6 +7,7 @@ from ivy_tests.test_ivy.test_functional.test_experimental.test_nn.test_layers import ( _x_and_ifft, _x_and_rfftn, + _x_and_iffttwo, ) @@ -153,6 +154,29 @@ def test_numpy_ifftshift( ) +@handle_frontend_test( + fn_tree="numpy.fft.iffttwo", + dtype_and_x=_x_and_iffttwo(), +) +def test_numpy_iffttwo( + dtype_and_x, backend_fw, frontend, test_flags, fn_tree, on_device +): + input_dtype, x, dim, norm, n = dtype_and_x + helpers.test_frontend_function( + input_dtypes=input_dtype, + frontend=frontend, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + test_values=True, + a=x, + s=None, + axes=None, + norm=norm, + ) + + @handle_frontend_test( fn_tree="numpy.fft.ihfft", dtype_input_axis=helpers.dtype_values_axis( diff --git a/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_layers.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_layers.py index a1cf596950cee..6dd38e597ef0e 100644 --- a/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_layers.py +++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_layers.py @@ -384,6 +384,42 @@ def _x_and_ifftn(draw): return dtype, x, s, axes, norm +@st.composite +def _x_and_iffttwo(draw): + min_fft_points = 2 + dtype = draw(helpers.get_dtypes("complex")) + x_dim = draw( + helpers.get_shape( + min_dim_size=2, max_dim_size=100, min_num_dims=1, max_num_dims=4 + ) + ) + x = draw( + helpers.array_values( + dtype=dtype[0], + shape=tuple(x_dim), + min_value=-1e-10, + max_value=1e10, + ) + ) + axes = draw( + st.lists( + st.integers(0, len(x_dim) - 1), min_size=1, max_size=len(x_dim), unique=True + ) + ) + norm = draw(st.sampled_from(["forward", "ortho", "backward"])) + + # Shape for s can be larger, smaller or equal to the size of the input + # along the axes specified by axes. + # Here, we're generating a list of integers corresponding to each axis in axes. + s = draw( + st.lists( + st.integers(min_fft_points, 256), min_size=len(axes), max_size=len(axes) + ) + ) + + return dtype, x, s, axes, norm + + @st.composite def _x_and_rfftn(draw): min_rfftn_points = 2 @@ -1011,6 +1047,34 @@ def test_ifftn( ) +@handle_test( + fn_tree="functional.ivy.experimental.iffttwo", + d_x_d_s_n=_x_and_iffttwo(), + ground_truth_backend="numpy", + test_gradients=st.just(False), +) +def test_iffttwo( + *, + d_x_d_s_n, + test_flags, + backend_fw, + fn_name, + on_device, +): + dtype, x, s, axes, norm = d_x_d_s_n + helpers.test_function( + input_dtypes=dtype, + test_flags=test_flags, + backend_to_test=backend_fw, + on_device=on_device, + fn_name=fn_name, + x=x, + s=s, + axes=axes, + norm=norm, + ) + + @handle_test( fn_tree="functional.ivy.experimental.interpolate", dtype_x_mode=_interp_args(),