Repository: ivy-llc/ivy

Issue:
rfftn function tensorflow modification
There is an issue with the recently added rfftn function in Ivy's backend, specifically in the TensorFlow implementation. It has come to our attention that the rfftn function in the TensorFlow backend is producing erroneous results, causing inconsistencies when called.


Discussion:

Resolving patch:
diff --git a/ivy/functional/backends/tensorflow/experimental/layers.py b/ivy/functional/backends/tensorflow/experimental/layers.py
--- a/ivy/functional/backends/tensorflow/experimental/layers.py
+++ b/ivy/functional/backends/tensorflow/experimental/layers.py
@@ -1291,7 +1291,7 @@ def ifftn(
 
 
 """
-RFFTN Function implementation
+RFFTN Function
 """
 
 
@@ -1321,15 +1321,14 @@ def rfft_operations(x, rank, norm_factor):
                 2: lambda: tf.signal.rfft3d(x),
             },
         )
-    # norm_factor = tf.cast(norm_factor, tf.complex64)
     norm_factor = tf.cast(norm_factor, tf.complex128)
-    x = x * norm_factor
+    x = x / norm_factor
+    x = tf.cast(x, tf.complex128)
     return x
 
 
 def _rfftn_helper(x, shape, axes, norm):
     x = rfft_input_validation(tf.convert_to_tensor(x))
-    # x = rfft_input_validation(x)
     input_shape = x.shape
     input_rank_tensor = tf.rank(x)
 
@@ -1391,77 +1390,3 @@ def rfftn(
     else:
         # return result
         return tf.cast(result, tf.complex128)
-
-
-# def _rfftn_norm(
-#     x: Union[tf.Tensor, tf.Variable],
-#     s: Sequence[int] = None,
-#     axes: Sequence[int] = None,
-#     norm: str = "backward",
-# ):
-#     n = tf.constant(s[-1] // 2 + 1, dtype=tf.complex128)
-#     if norm == "backward":
-#         return x
-#     elif norm == "ortho":
-#         return x / tf.sqrt(n)
-#     elif norm == "forward":
-#         return x / n
-#     else:
-#         raise ivy.utils.exceptions.IvyError(f"Unrecognized normalization mode {norm}")
-
-
-# @with_unsupported_dtypes(
-#     {"0.4.14 and below": ("float32", "complex")}, backend_version
-# )
-# def rfftn(
-#     x: Union[tf.Tensor, tf.Variable],
-#     s: Sequence[int] = None,
-#     axes: Sequence[int] = None,
-#     *,
-#     norm: str = "backward",
-#     out: Optional[Union[tf.Tensor, tf.Variable]] = None,
-# ) -> Union[tf.Tensor, tf.Variable]:
-#     if axes is None:
-#         axes = list(range(len(s)))
-#     elif s is None:
-#         s = [x.shape[axis] for axis in axes]
-#     elif len(s) != len(axes):
-#         raise ValueError("s and axes must have the same length.")
-
-#     if not all(isinstance(j, int) for j in s):
-#         raise ivy.utils.exceptions.IvyError(
-#             f"Expecting {s} to be a sequence of integers <class integer>"
-#         )
-#     if all(j <= 1 for j in s):
-#         raise ivy.utils.exceptions.IvyError(
-#             f"Invalid data points {s}, expecting s points larger than 1"
-#         )
-#     if norm != "backward" and norm != "ortho" and norm != "forward":
-#         raise ivy.utils.exceptions.IvyError(f"Unrecognized normalization mode {norm}")
-
-
-#     if len(s) != 2:
-#         raise ValueError("fft_length must have shape [2]")
-#     fft_length = tf.convert_to_tensor(s, dtype=tf.int32)
-
-#     # Convert s to a tensor with shape [2]
-#     # fft_length = tf.convert_to_tensor(s, dtype=tf.int32)
-#     # if tf.shape(fft_length).shape != [1] or tf.shape(fft_length).as_list()[0] != 2:
-#     #     raise ValueError("fft_length must have shape [2]")
-#     operation_name = f"RFFTn with s={s}, axes={axes}, norm={norm}"
-#     # tf_rfftn = tf.signal.rfft2d(x, fft_length=fft_length, name=operation_name)
-
-# # Reshape the input tensor to 2D
-#     x_2d = tf.reshape(x, [-1, s[0]])
-
-#     # Perform rfft2d operation on the reshaped tensor
-#     tf_rfftn_2d = tf.signal.rfft2d(x_2d, fft_length=s[1], name=operation_name)
-
-#     # Reshape the result back to the original shape
-#     output_shape = tf.concat([tf.shape(x)[:-1], [s[-1] // 2 + 1]], axis=0)
-#     tf_rfftn = tf.reshape(tf_rfftn_2d, output_shape)
-
-
-#     # Apply the same normalization as 'backward' in NumPy
-#     tf_rfftn = _rfftn_norm(tf_rfftn, s, axes, norm, out).astype("complex128")
-#     return tf_rfftn


Test patch:
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
--- 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
@@ -1212,7 +1212,7 @@ def x_and_rfftn(draw):
     dtype = draw(helpers.get_dtypes("float"))
     x_dim = draw(
         helpers.get_shape(
-            min_dim_size=2, max_dim_size=100, min_num_dims=2, max_num_dims=3
+            min_dim_size=2, max_dim_size=100, min_num_dims=1, max_num_dims=3
         )
     )
     x = draw(
@@ -1261,8 +1261,8 @@ def test_rfftn(
         backend_to_test=backend_fw,
         on_device=on_device,
         fn_name=fn_name,
-        rtol_=0.8,
-        atol_=0.8,
+        rtol_=1e-2,
+        atol_=1e-2,
         x=x,
         s=s,
         axes=axes,