Repository: ivy-llc/ivy

Issue:
norm



Discussion:

Resolving patch:
diff --git a/ivy/functional/frontends/paddle/tensor/linalg.py b/ivy/functional/frontends/paddle/tensor/linalg.py
--- a/ivy/functional/frontends/paddle/tensor/linalg.py
+++ b/ivy/functional/frontends/paddle/tensor/linalg.py
@@ -1,6 +1,6 @@
 # global
 import ivy
-from ivy.func_wrapper import with_unsupported_dtypes
+from ivy.func_wrapper import with_unsupported_dtypes, with_supported_dtypes
 from ivy.functional.frontends.paddle import promote_types_of_paddle_inputs
 from ivy.functional.frontends.paddle.func_wrapper import (
     to_ivy_arrays_and_back,
@@ -15,6 +15,65 @@ def matmul(x, y, transpose_x=False, transpose_y=False, name=None):
     return ivy.matmul(x, y, transpose_a=transpose_x, transpose_b=transpose_y)
 
 
+# norm
+@with_supported_dtypes({"2.4.2 and below": ("float32", "float64")}, "paddle")
+@to_ivy_arrays_and_back
+def norm(x, p="fro", axis=None, keepdim=False, name=None):
+    if axis is None and p is not None:
+        if p == "fro":
+            p = 2
+        ret = ivy.vector_norm(x.flatten(), ord=p, axis=-1)
+        if keepdim:
+            ret = ret.reshape([1] * len(x.shape))
+        if len(ret.shape) == 0:
+            return ivy.array([ret])
+        return ret
+
+    if isinstance(axis, tuple):
+        axis = list(axis)
+    if isinstance(axis, list) and len(axis) == 1:
+        axis = axis[0]
+
+    if isinstance(axis, int):
+        if p == "fro":
+            p = 2
+        if p in [0, 1, 2, ivy.inf, -ivy.inf]:
+            ret = ivy.vector_norm(x, ord=p, axis=axis, keepdims=keepdim)
+        elif isinstance(p, (int, float)):
+            ret = ivy.pow(
+                ivy.sum(ivy.pow(ivy.abs(x), p), axis=axis, keepdims=keepdim),
+                float(1.0 / p),
+            )
+
+    elif isinstance(axis, list) and len(axis) == 2:
+        if p == 0:
+            raise ValueError
+        elif p == 1:
+            ret = ivy.sum(ivy.abs(x), axis=axis, keepdims=keepdim)
+        elif p == 2 or p == "fro":
+            ret = ivy.matrix_norm(x, ord="fro", axis=axis, keepdims=keepdim)
+        elif p == ivy.inf:
+            ret = ivy.max(ivy.abs(x), axis=axis, keepdims=keepdim)
+        elif p == -ivy.inf:
+            ret = ivy.min(ivy.abs(x), axis=axis, keepdims=keepdim)
+        elif isinstance(p, (int, float)) and p > 0:
+            ret = ivy.pow(
+                ivy.sum(ivy.pow(ivy.abs(x), p), axis=axis, keepdims=keepdim),
+                float(1.0 / p),
+            )
+        else:
+            raise ValueError
+
+    else:
+        raise ValueError
+
+    if len(ret.shape) == 0:
+        ret = ivy.array(
+            [ret]
+        )  # this is done so as to match shape of output from paddle
+    return ret
+
+
 # eig
 @to_ivy_arrays_and_back
 def eig(x, name=None):


Test patch:
diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_tensor/test_paddle_linalg.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_tensor/test_paddle_linalg.py
--- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_tensor/test_paddle_linalg.py
+++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_tensor/test_paddle_linalg.py
@@ -59,6 +59,53 @@ def _get_dtype_and_square_matrix(draw, real_and_complex_only=False):
     return dtype, mat
 
 
+@st.composite
+def _dtype_values_axis(draw):
+    dtype_and_values = draw(
+        helpers.dtype_and_values(
+            available_dtypes=helpers.get_dtypes("float"),
+            min_num_dims=2,
+            max_num_dims=5,
+            min_dim_size=2,
+            max_dim_size=5,
+            min_value=0.1,
+            max_value=1000.0,
+        )
+    )
+
+    dtype, x = dtype_and_values
+    x = x[0]
+    r = len(x.shape)
+
+    valid_axes = [None]
+
+    for i in range(-r, r):
+        valid_axes.append(i)
+        for j in range(-r, r):
+            if i != j and abs(i - j) != r:
+                valid_axes.append([i, j])
+
+    axis = draw(st.sampled_from(valid_axes))
+
+    p_list = ["fro", 1, 2, ivy.inf, -ivy.inf]
+    if isinstance(axis, list) and len(axis) == 2:
+        p = draw(
+            st.one_of(
+                st.sampled_from(p_list),
+                st.floats(min_value=1.0, max_value=10.0, allow_infinity=False),
+            )
+        )
+    else:
+        p = draw(
+            st.one_of(
+                st.sampled_from(p_list + [0]),
+                st.floats(min_value=1.0, max_value=10.0, allow_infinity=False),
+            )
+        )
+
+    return dtype, x, axis, p
+
+
 # Tests #
 # ----- #
 
@@ -103,6 +150,37 @@ def test_paddle_matmul(
     )
 
 
+# norm
+@handle_frontend_test(
+    fn_tree="paddle.tensor.linalg.norm",
+    dtype_values_axis=_dtype_values_axis(),
+    keepdims=st.booleans(),
+    test_with_out=st.just(False),
+)
+def test_paddle_norm(
+    dtype_values_axis,
+    keepdims,
+    frontend,
+    test_flags,
+    fn_tree,
+    on_device,
+):
+    dtype, x, axis, p = dtype_values_axis
+    helpers.test_frontend_function(
+        input_dtypes=dtype,
+        frontend=frontend,
+        test_flags=test_flags,
+        fn_tree=fn_tree,
+        on_device=on_device,
+        x=x,
+        p=p,
+        axis=axis,
+        keepdim=keepdims,
+        atol=1e-1,
+        rtol=1e-1,
+    )
+
+
 # eig
 @handle_frontend_test(
     fn_tree="paddle.tensor.linalg.eig",